1、互斥量概念
互斥量是个类对象。
理解成一把锁,多个线程尝试使用lock()成员函数来加锁,只有一个线程能锁定成功。
如果没有锁定成功,那么流程卡在lock()这里不断的尝试去锁住这把锁头。
互斥量使用要小心,保护数据不多也不少,少了,没达到保护的效果,多了,影响效率。
2、互斥量用法
(1)lock(),unlock()
lock() 和unlock()要成对使用,有lock(),必然有unlock()。
不应该也不允许调用了一次lock(),却调用多次unlock()。
std::mutex my_mutex;
//.........
my_mutex.lock();
//...............
my_mutex.unlock();
为了防止大家忘记unlock(),引入了一个 stdlock_guard() 类的模板。
(2)std::lock_guard()
使用std::lock_guard(),直接取代lock()和unlock(), 可以解决忘记上述(1)法忘记使用unlock()造成的问题。
使用lock_guard之后,再不能使用lock() 和unlock()。
std::mutex my_mutex;
//...............
std::lock_guard(std::mutex) sbguard(my_mutex);
3、死锁原因及解决方法
(1)造成死锁的原因
死锁至少两个互斥量才能产生。
如:现有金锁、银锁
两个线程A、B
(1)线程A执行的时候,这个线程先锁金锁,把金锁lock()成功后,然后锁银锁;
//出现上下文切换
(2)线程B执行了,这个线程先锁银锁,因为银锁还没被锁,所以银锁lock成功,线程B要去lock金锁…
//这样死锁就产生了。
(3)线程A因为拿不到银锁头,流程走不下去。
(4)线程B因为拿不到金锁头,流程走不下去。
(2)死锁的一般解决方法
只要保证这两个互斥量的顺序一致就不会死锁。
(3)std::lock()函数模板:用来处理多个互斥量
能力:一次锁住两个或者两个以上的互斥量(至少两个)。
它不存在因为在多个线程中,因为锁的顺序问题导致死锁的风险。
std::lock():如果互斥量有一个没锁住,它就在那里等着,等所有的互斥量都锁住,它才能继续往下走(返回);
要么两个互斥量都锁住,两个互斥量都没锁住。如果只锁了一个,另外一个没锁成功,则它立即把已经锁住的解锁。
std::lock(my_mutex1, my_mutex2);
//.............
my_mutex1.unlock();
my_mutex2.unlock();
(4)std::lock_guard()的参数std::adopt_lock函数
std::lock(my_mutex1, my_mutex2);
//前面已经lock该互斥量,这里工作仅是在析构函数中会调用该互斥量的unlock
std::lock_guard(std::mutex) sbguard(my_mutex1,std::adopt_lock);
std::lock_guard(std::mutex) sbguard(my_mutex2,std::adopt_lock);