六、unique_lock

一、unique_lock取代lock_guard

是个类模板,一般用lock_guard,unique_guard更灵活,效率差一点,内存占用多了一点。

二、unique_lock 的第二个参数

1、std::adopt_lock

就是个标记,表示位于第一个参数的互斥量已经lock了。(你必须先把这个互斥量lock,否则会报异常)

2、std::try_to_lock

正常情况下线程A锁住一个mutex,然后要求等待10秒,这个时候另一个线程B要锁这个mutex,但是由于线程A没有解锁这个mutex,那么线程B相当于也要等至少10秒钟,会卡在这里,等A解锁了这个mutex才能去拿这个锁。对于这种情况,unique_lock就能够灵活的处理。

unique_lock的try_to_lock参数会尝试用mutex的lock()去锁住这个mutex,但如果没有锁定成功,也会立即返回,并不会阻塞在那里。(前提是你自己不能先去lock)

 1 void InMsgQue(){
 2     for(int i=0;i<100;i++){
 3         cout<<"InMsgQue执行,插入一个元素"<<i<<endl;
 4         std::unique_lock<std::mutex> my_lock(my_mutex1,std::try_to_lock);
 5         if(my_lock.owns_lock()){//判断是否拿到了锁
 6             //拿到了锁。。。。。
 7         }
 8         else{
 9             //没拿到锁的话要做的事情
10         }
11         MyQue.push_back(i);//假设i就是命令
12         //其他处理代码、、、、、、、
13     }
14 }

3、std::defer_lock

前期:不能自己先去lock

并没有给mutex加锁,初始化了一个没有加锁的mutex,这样就方便里调用一些unique_lock的一些成员函数。

 1 void InMsgQue(){
 2     for(int i=0;i<100;i++){
 3         cout<<"InMsgQue执行,插入一个元素"<<i<<endl;
 4         std::unique_lock<std::mutex> my_lock(my_mutex1,std::defer_lock);//没有枷锁的mutex,相当于将my_mutex1和my_lock绑定一起了
 5         my_lock.lock();//不用自己unlock
 6         if(my_lock.owns_lock()){//判断是否拿到了锁
 7             //拿到了锁。。。。。
 8         }
 9         else{
10             //没拿到锁
11         }
12         MyQue.push_back(i);//假设i就是命令
13         //其他处理代码、、、、、、、
14     }
15 }

 

三、unique_lock成员函数

1、lock

2、unlock

配合defer_lock参数

unique_lock可以自己unlock了,为什么还要有unlock这个成员函数?

void InMsgQue(){
    for(int i=0;i<100;i++){
        cout<<"InMsgQue执行,插入一个元素"<<i<<endl;
        std::unique_lock<std::mutex> my_lock(my_mutex1,std::defer_lock);//没有枷锁的mutex,相当于将my_mutex1和my_lock绑定一起了
        my_lock.lock();//不用自己unlock
        //有时候有一些非共享代码要去处理,所以先unlock
        my_lock.unlock();
        //接着处理一些共享代码
        my_lock.lock();
    //其他处理代码.......
    //my_lock.unlock();//画蛇添足,unique_lock的析构函数会unlock,但是也不会出问题
}

为什么有时候需要unlock()?

因为lock锁住的代码越少,执行越快,整个程序运行效率就越高。

有人也把锁住的代码多少称为锁的粒度,粒度一般用粗细来秒速。

锁住的代码少,粒度细,执行效率高;

锁住的代码高,粒度粗,执行效率低;

要尽量选择合适的粒度,粒度太细,可能漏掉对共享数据的保护,粒度太粗,影响效率。

3、try_lock

配合defer_lock使用。

 1 void InMsgQue(){
 2     for(int i=0;i<100;i++){
 3         cout<<"InMsgQue执行,插入一个元素"<<i<<endl;
 4         std::unique_lock<std::mutex> my_lock(my_mutex1,std::defer_lock);//没有枷锁的mutex,相当于将my_mutex1和my_lock绑定一起了
 5         if(my_lock.try_lock()==true){
 6             //如果拿到锁了。。。。。
 7         }
 8         else{
 9             //如果没拿到所
10         }
11     }
12 }

 

4、release

返回它管理的mutex对象指针,释放所有权,也就是这个unique_lock和mutex不再有关系。

和unlock不同的,不要混淆。

1 void InMsgQue(){
2     for(int i=0;i<100;i++){
3         std::unique_lock<std::mutex> my_lock(mutex1);
4         std::mutex *ptx = my_lock.release();//断开my_lock和mutex1的关系,所以你要自己解锁了
5         ptx->unlock();//自己负责mutex1的unlock
6         cout<<"InMsgQue执行,插入一个元素"<<i<<endl;
7     }
8 }

四、unique_lock所有权的传递
一个unique_lock要只和一个mutex绑定在一起,也就是一个unique_lock只管理一个mutex。

my_lock也就是拥有mutex1的所有权。

my_lock可以把自己对mutex1的所有权 是属于可以转移,不能复制。

unique_lock也可以作为函数定义时的返回类型的:

1 std::unique_lock<std::mutex> my_lock(){
2     std::unique_lock<std::mutex> temp_lock(mutex1);
3     return temp_lock;
4 }
5 std::unique_lock<std::mutex> new_lock = my_lock();

 

posted @ 2019-07-23 17:29  Austin_anheqiao  阅读(615)  评论(0编辑  收藏  举报