当前位置: 首页 > news >正文

c++ std::mutex与std::condition_variable

1. std::mutex

lock()加锁;  try_lock()尝试加锁; unlock()解锁;

std::mutex m_mutex;    m_mutex.lock();
...
m_mutex.unlock();

2. std::lock_guard

 类模板;等同自动锁,直接取代lock()和unlock(); 构造时加锁,析构时解锁;

std::mutex m_mutex;
{std::lock_guard<std::mutex> myLock(m_mutex);...
} //作用域执行完,自动unlock解锁;

3. std::unique_lock

类模板, 比lock_guard灵活,效率比lock_guard差一点,内存占用比lock_guard多一点;所以工作中使用lock_guard就够了;

3.1 unuque_lock的第二参数

std::adopt_lock:   表示互斥量已经被lock()了 (互斥量必须提前lock()否则错误); 

std::mutex m_mutex;
{m_mutex.lock();std::unique_lock<std::mutex> myLock(m_mutex, std::adopt_lock);
}

std::defer_lock: 没有给mutex加锁,初始化一个没有加锁的mutex; 故不能提前自己加锁,否则错误;

std::mutex m_mutex;{//之前不能加锁std::unique_lock<std::mutex> myLock(m_mutex, std::defer_lock);myLock.lock();}

std::try_to_lock:  尝试用mutex加锁,加锁失败会立即返回,不阻塞; 前提是不能自己先加锁;

std::mutex m_mutex;
{//之前不能加锁std::unique_lock<std::mutex> myLock(m_mutex, std::try_to_lock);if (myLock.owns_lock()) {std::cout << "get lock suc" << std::endl;}else {std::cout << "get lock failed" << std::endl;}
}

3.2 成员函数

lock(): 加锁;

unlock():解锁;

std::mutex m_mutex;
{std::unique_lock<std::mutex> myLock(m_mutex);...myLock.unlock();myLock.lock();...myLock.unlock(); //可加可不加
}

 try_lock():尝试加锁;

owns_lock(): 加锁成功返回true, 加锁失败返回false;

release(): 返回管理的锁对象指针,并将其置空;

//若原来 mutex处于加锁状态,那么接管过来需要我们自己解锁;
std::unique_lock<std::mutex> myLock(m_mutex1);
std::timed_mutex *ptx = myLock.release();//现在你有责任自己解锁了;
ptx->unlock();

4. std::condition_variable

条件变量,用于线程同步; 搭配std::mutex一起使用;

 4.1 wait

/* 源码 */
void wait(unique_lock<mutex>& _Lck) { // wait for signal// Nothing to do to comply with LWG-2135 because std::mutex lock/unlock are nothrow_Cnd_wait(_Mycnd(), _Lck.mutex()->_Mymtx());
}template <class _Predicate>
void wait(unique_lock<mutex>& _Lck, _Predicate _Pred) { // wait for signal and test predicatewhile (!_Pred()) {wait(_Lck);}
}

带有_Predicate 的重载函数用于判断条件是否满足;

std::mutex m_mutex;
std::condition_variable m_cond;{std::unique_lock<std::mutex> lock(m_mutex);#if 1/*wait将解锁互斥量,并阻塞到本行, 直到其他某个线程调用notify_one/all唤醒;当被唤醒后,wait()尝试获取互斥量;获取成功即上锁;判断参数2 lambda结果,为false则解锁,阻塞本行;为true,则wait()返回,继续执行下面代码;*/m_cond.wait(lock, [this] {if (条件==true) return true;return false;});...#else//wait将解锁互斥量,并阻塞到本行; 直到其他某个线程调用notify_one/all唤醒;//wait()后从新获取锁; 获取成功直接返回,继续下面流程m_cond.wait(lock);流程走到这里, lock一定是锁着的;#endif
}

4.2 notify

notify_one: 唤醒wait等待的一个线程,只能唤醒一次;

notify_all: 唤醒wait等待的所有线程,广播形式全部通知; 但是只有一个获取锁成功;

//m_cond.notify_one(); //唤醒一个
m_cond.notify_all();//唤醒多个线程

http://www.lryc.cn/news/143294.html

相关文章:

  • Aspose.Tasks for .NET V23Crack
  • vue过渡及动画
  • Linux环境下SVN服务器的搭建与公网访问:使用cpolar端口映射的实现方法
  • 【ubuntu】 DNS 设置工具 resolvectl
  • Keepalived+Lvs(dr)调度器主备配置小实验
  • 第四讲Java基本语法——数组结构(多维数组)
  • 【题解】JZOJ6578 / 洛谷P5201[USACO2019Jan]Shortcut G
  • npm install sentry-cli失败的问题
  • Node opensslErrorStack 错误解决方法记录
  • 你知道什么是Grandmillennial风格吗,进来看看吧
  • App Inventor 2 开发 ChatGPT 对话App
  • SQL 大小敏感问题
  • 微信小程序+Taro 混编,Taro 使用微信原生 behaviors
  • b树/b+树、时间轮、跳表、LSM-Tree
  • Unity OnDrawGizmos的简单应用 绘制圆形
  • Uniapp笔记(四)uniapp语法3
  • leetcode做题笔记105. 从前序与中序遍历序列构造二叉树
  • Python里的列表List求和
  • 启动docker容器的几种方法和注意事项(docker-compose,dockerfile)
  • bash: conda: command not found
  • Leetcode-每日一题【剑指 Offer 36. 二叉搜索树与双向链表】
  • ctfshow-萌新专属红包题
  • 谷歌面试-扔鸡蛋
  • Unity血条制作
  • vue,uniapp生成二维码
  • 分类预测 | MATLAB实现SSA-CNN-SVM基于麻雀算法优化卷积支持向量机分类预测
  • STM32启动模式详解
  • go语言中的切片
  • HTML-常见标签、HTML5新特性
  • 微信有自己的“知乎”,微信问一问来了!