把共享数据锁住,操作数据,解锁
其他线程等待解锁,上锁,操作,解锁
#include
mutex mtx;
//lock()与unlock()成对使用
mtx.lock()
//......
mtx.unlock()
//等价于 不能和lock()混用
lock_guard<mutex> lk(mtx); //生成lock_guard的对象lk 类的构造函数里执行了mutex::lock() 析构函数里执行了mutex::unlock() return 之前才能析构
//可以利用{} 对数据进行析构 可以提前结束lock_guard的生命周期 可以达到提前析构 若后面还有大量代码 若为return 无需{}
为了防止大家忘记unlock(),引入了lock_guard() 类似于独占式智能指针 会自动lock
一个互斥量就是一把锁
死锁必须要至少有两把锁 也就是两个互斥量
两把锁 金锁 银锁
两个线程 A B
(1)线程A 缩金锁 将要去锁银锁
//出现了上下文切换
(2)线程B 锁银锁 将要去锁金锁
//发生了死锁
(3)线程A因为拿不到银锁 后面的代码有解锁金锁但是走不下去
线程B因为拿不到金锁 后面的代码有解锁银锁但是走不下去
mutex mtx1;
mutex mtx2;
//线程A
mtx1.lock();
//.......
mtx2.lock();
mtx2.unlock();
mtx1.unlock();
//线程B
mtx2.lock();
mtx1.lock();
mtx1.unlock();
mtx2.unlock();
//lock()函数
lock(mtx1, mtx2);
mtx2.unlock();
mtx1.unlock();
//等同于adopt_lock
lock(mtx1, mtx2);
lock_guard<mutex> lk1(mtx1, adopt_lock); //取代mtx2.unlock()
lock_guard<mutex> lk2(mtx2, adopt_lock);
如何解决问题:
保持一样的顺序 都是先锁1后锁2
lock()函数可以同时锁住多个变量 至少两个 防止出现死锁
如果互斥量中有一个没锁住,会立刻释放已经锁住的互斥量 要么两个互斥量都锁柱 要么两个互斥量都没锁住
adopt_lock 是一个结构体对象 表示对象已经lock过了 不需要在lock_guard中再对对象进程lock(), unlock()照常
https://www.bilibili.com/video/BV1Yb411L7ak?p=7&vd_source=3faf892a87f05b733e8d196b0c30eada
第1节 第2节 join detach joinable
第5节 mutex 死锁
第8节 condition_variable wait notify_one notify_all
第10节 第11节 tomic 原子操作
第12节 临界区
第13节 线程池 多线程