博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[c++11]多线程编程(五)——unique_lock
阅读量:7187 次
发布时间:2019-06-29

本文共 2465 字,大约阅读时间需要 8 分钟。

互斥锁保证了线程间的同步,但是却将并行操作变成了串行操作,这对性能有很大的影响,所以我们要尽可能的减小锁定的区域,也就是使用细粒度锁

这一点lock_guard做的不好,不够灵活,lock_guard只能保证在析构的时候执行解锁操作,lock_guard本身并没有提供加锁和解锁的接口,但是有些时候会有这种需求。看下面的例子。

class LogFile {    std::mutex _mu;    ofstream f;public:    LogFile() {        f.open("log.txt");    }    ~LogFile() {        f.close();    }    void shared_print(string msg, int id) {        {            std::lock_guard
guard(_mu); //do something 1 } //do something 2 { std::lock_guard
guard(_mu); // do something 3 f << msg << id << endl; cout << msg << id << endl; } }};

上面的代码中,一个函数内部有两段代码需要进行保护,这个时候使用lock_guard就需要创建两个局部对象来管理同一个互斥锁(其实也可以只创建一个,但是锁的力度太大,效率不行),修改方法是使用unique_lock。它提供了lock()unlock()接口,能记录现在处于上锁还是没上锁状态,在析构的时候,会根据当前状态来决定是否要进行解锁(lock_guard就一定会解锁)。上面的代码修改如下:

class LogFile {    std::mutex _mu;    ofstream f;public:    LogFile() {        f.open("log.txt");    }    ~LogFile() {        f.close();    }    void shared_print(string msg, int id) {        std::unique_lock
guard(_mu); //do something 1 guard.unlock(); //临时解锁 //do something 2 guard.lock(); //继续上锁 // do something 3 f << msg << id << endl; cout << msg << id << endl; // 结束时析构guard会临时解锁 // 这句话可要可不要,不写,析构的时候也会自动执行 // guard.ulock(); }};

上面的代码可以看到,在无需加锁的操作时,可以先临时释放锁,然后需要继续保护的时候,可以继续上锁,这样就无需重复的实例化lock_guard对象,还能减少锁的区域。同样,可以使用std::defer_lock设置初始化的时候不进行默认的上锁操作:

void shared_print(string msg, int id) {    std::unique_lock
guard(_mu, std::defer_lock); //do something 1 guard.lock(); // do something protected guard.unlock(); //临时解锁 //do something 2 guard.lock(); //继续上锁 // do something 3 f << msg << id << endl; cout << msg << id << endl; // 结束时析构guard会临时解锁}

这样使用起来就比lock_guard更加灵活!然后这也是有代价的,因为它内部需要维护锁的状态,所以效率要比lock_guard低一点,在lock_guard能解决问题的时候,就是用lock_guard,反之,使用unique_lock

后面在学习条件变量的时候,还会有unique_lock的用武之地。

另外,请注意,unique_locklock_guard都不能复制,lock_guard不能移动,但是unique_lock可以!

// unique_lock 可以移动,不能复制std::unique_lock
guard1(_mu);std::unique_lock
guard2 = guard1; // errorstd::unique_lock
guard2 = std::move(guard1); // ok// lock_guard 不能移动,不能复制std::lock_guard
guard1(_mu);std::lock_guard
guard2 = guard1; // errorstd::lock_guard
guard2 = std::move(guard1); // error

参考

转载地址:http://msykm.baihongyu.com/

你可能感兴趣的文章
家庭宽带之IPv6网络测试
查看>>
让宏哥告诉你什么叫做 OO -- 放在博客比较有价值
查看>>
filter的时间过滤有关问题
查看>>
access手工注入笔记
查看>>
zookeeper原理(转)
查看>>
垂直居中的几种方法
查看>>
我的友情链接
查看>>
PTN960
查看>>
$_FILES[‘file’][‘error’] 错误代码和相关的错误常量
查看>>
将项目加入maven管理时报错
查看>>
Qt线程
查看>>
数据库小知识
查看>>
ASP.NET WEB API必知必会:特性路由
查看>>
'Worker' object has no attribute '_config'
查看>>
微信支付开发H5调用支付接口失败
查看>>
IIS安装及IIS无权访问解决方法(Failed to access IIS metabase解决)
查看>>
Oracle下ORA-28002错误处理
查看>>
新方法让纳米材料组装合成“指哪长哪”
查看>>
springboot及微服务
查看>>
【unity】手势操作之初识FingerGestures
查看>>