0
点赞
收藏
分享

微信扫一扫

[modern c++] std::unique_lock的使用及其必要性


unique_lock在构造时的灵活性:

#include <iostream>
#include <Windows.h>
#include <mutex>
using namespace std;

void CriticalSection_2();

mutex m1;

void CriticalSection_1()
{
unique_lock<mutex> lockguard(m1);
CriticalSection_2();
}

void CriticalSection_2()
{

//场景一
//unique_lock<mutex> lockguard(m1); //崩溃,对已经加锁的 mutex 再加锁导致崩溃


//场景二
//unique_lock<mutex> lockguard(m1, try_to_lock_t()); //正常,对已经加锁的 mutex 尝试加锁不会导致崩溃


//场景三
//unique_lock<mutex> lockguard(m1, defer_lock_t()); //正常,对已经加锁的 mutex 不加锁不会崩溃
//m1.lock(); //奔溃,对已经加锁的 mutex 再加锁导致崩溃


//场景四
//unique_lock<mutex> lockguard(m1, adopt_lock_t()); //崩溃

}


int main()
{
CriticalSection_1();

std::cout << "Hello World!\n";
while (1) Sleep(1000);
}

unique_lock在使用中的灵活性:

  • 可以随时解锁(lock_guard无法做到,虽然通过mutex.unlock()也可以完成,但是unique_lock提供了自释放功能)

#include <iostream>
#include <Windows.h>
#include <mutex>
using namespace std;

void CriticalSection_2();

mutex m1;

void CriticalSection_1()
{
unique_lock<mutex> lockguard(m1);
lockguard.unlock();
CriticalSection_2();
}

void CriticalSection_2()
{
unique_lock<mutex> lockguard(m1); //正常,前面已经通过lockguard.unlock();进行了解锁
}


int main()
{
CriticalSection_1();

std::cout << "Hello World!\n";
while (1) Sleep(1000);
}

  • 析构时会自动判断当前是否持有锁(对已经释放的锁再释放会导致崩溃,unique_lock在析构函数中会判断当前锁是否已经被释放)

#include <iostream>
#include <Windows.h>
#include <mutex>
using namespace std;

mutex m1;

void CriticalSection_1()
{
unique_lock<mutex> lockguard(m1);
#if 1
lockguard.unlock(); //不会奔溃,虽然lockguard.unlock();被显式调用,但是lockguard析构不会导致崩溃
#else
m1.unlock(); //会崩溃,这里也要强调一点,如果打算使用unique_lock就不要在对原始的mutex进行任何操作
#endif
}


int main()
{
CriticalSection_1();
std::cout << "Hello World!\n";
while (1) Sleep(1000);
}

注意:

如果确定使用unique_lock了,就不要再使用 mutex 的 lock 和 unlock ,直接使用 unique_lock 的 lock 和 unlock,混合使用会导致程序异常,原因是unique_lock 内部会维护一个标识用来记录自己管理的 锁 当前处于何种状态,如果直接使用 mutex的成员函数,unique_lock无法更新自己的状态,从而导致 double lock 和 double unlock(因为unique_lock一定会在析构的时候unlock),这两种情况都会导致崩溃。

PS:

上面的崩溃不会发生在 递归锁上,所以上文中所有的锁 都是非递归锁,比如 mutex。

对比unique_lock 和 lock_guard:

  • 二者都是自释放锁;
  • lock_guard 在时间和空间上都比 unique_lock 要快;
  • lock_guard 功能单一,只能用作自释放锁;
  • unique_lock具备lock_guard的所有能力,同时提供更多的能力,比如锁的成员函数都会被封装后导出,同时不会引入 double lock 和 double unlock ;
举报

相关推荐

0 条评论