• 六、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();
  • 相关阅读:
    (转)分布式加载网站的静态文件
    (转)一步一步Asp.Net MVC系列_权限管理设计起始篇
    (转)SQL Server复制入门(一)复制简介
    (转)【配置属性】—Entity Framework实例详解
    (转)动态Entity Framework查询:Dynamic Query 介绍
    (转)用扩展方法优化多条件查询
    (转)一步一步Asp.Net MVC系列_权限管理之权限控制
    (转 )Entity Framework Code First使用者的福音 EF Power Tool使用记之二(问题探究)
    (转)【工欲善其事必先利其器】—Entity Framework实例详解
    (转)C#/winform 腾讯QQ注册
  • 原文地址:https://www.cnblogs.com/pacino12134/p/11233199.html
Copyright © 2020-2023  润新知