C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢导致程序出现未定义的行为。通常的做法是在修改共享数据成员的时候进行加锁--mutex。在使用锁的时候通常是在对共享数据进行修改之前进行lock操作,在写完之后再进行unlock操作,进场会出现由于疏忽导致由于lock之后在离开共享成员操作区域时忘记unlock,导致死锁。

针对以上的问题,C++11中引入了std::unique_lock与std::lock_guard两种数据结构。通过对lock和unlock进行一次薄的封装,实现自动unlock的功能。

  1. std::mutex mut;
  2. void insert_data()
  3. {
  4. std::lock_guard<std::mutex> lk(mut);
  5. queue.push_back(data);
  6. }
  7. void process_data()
  8. {
  9. std::unqiue_lock<std::mutex> lk(mut);
  10. queue.pop();
  11. }

std::unique_lock 与std::lock_guard都能实现自动加锁与解锁功能,但是std::unique_lock要比std::lock_guard更灵活,但是更灵活的代价是占用空间相对更大一点且相对更慢一点。

通过实现一个线程安全的队列来说明两者之间的差别。

  template <typename T>

  1. class ThreadSafeQueue{
  2. public:
  3. void Insert(T value);
  4. void Popup(T &value);
  5. bool Empety();
  6. private:
  7. mutable std::mutex mut_;
  8. std::queue<T> que_;
  9. std::condition_variable cond_;
  10. };

  template <typename T>

  1. void ThreadSafeQueue::Insert(T value){
  2. std::lock_guard<std::mutex> lk(mut_);
  3. que_.push_back(value);
  4. cond_.notify_one();
  5. }
  6. template <typename T>
  7. void ThreadSafeQueue::Popup(T &value){
  8. std::unique_lock<std::mutex> lk(mut_);
  9. cond_.wait(lk, [this]{return !que_.empety();});
  10. value = que_.front();
  11. que_.pop();
  12. }
  13. template <typename T>
  14. bool ThreadSafeQueue::Empty() const{
  15. std::lock_guard<std::mutex> lk(mut_);
  16. return que_.empty();
  17. }

上面代码只实现了关键的几个函数,并使用了C++11新引入的condition_variable条件变量。从Popup与Inert两个函数看std::unique_lock相对std::lock_guard更灵活的地方在于在等待中的线程如果在等待期间需要解锁mutex,并在之后重新将其锁定。而std::lock_guard却不具备这样的功能。

上面代码中

可能会比较难以理解,

  [this]{return !Empety();}

是C++11新引入的功能,lambda表达式,是一种匿名函数。方括号内表示捕获变量。当lambda表达式返回true时(即queue不为空),wait函数会锁定mutex。当lambda表达式返回false时,wait函数会解锁mutex同时会将当前线程置于阻塞或等待状态。

还存在另一种读写锁,但是并没有引入C++11,但是boost库提供了对应的实现。读写锁主要适合在于共享数据更新频率较低,但是读取共享数据频率较高的场合。

std::lock_guard/std::unique_lock的更多相关文章

  1. C++ folly库解读(三)Synchronized —— 比std::lock_guard/std::unique_lock更易用、功能更强大的同步机制

    目录 传统同步方案的缺点 folly/Synchronized.h 简单使用 Synchronized的模板参数 withLock()/withRLock()/withWLock() -- 更易用的加 ...

  2. 基于std::mutex std::lock_guard std::condition_variable 和std::async实现的简单同步队列

    C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢导致程序出现未定义的行为.通常的做法是在修改共享数据成员的时候进行加锁--mutex.在使用锁的时候通 ...

  3. std::unique_lock<std::mutex> or std::lock_guard<std::mutex> C++11 区别

    http://stackoverflow.com/questions/20516773/stdunique-lockstdmutex-or-stdlock-guardstdmutex The diff ...

  4. C++ 11 多线程下std::unique_lock与std::lock_guard的区别和用法

    这里主要介绍std::unique_lock与std::lock_guard的区别用法 先说简单的 一.std::lock_guard的用法 std::lock_guard其实就是简单的RAII封装, ...

  5. std::lock_guard和std::unique_lock

    std::unique_lock也可以提供自动加锁.解锁功能,比std::lock_guard更加灵活 https://www.cnblogs.com/xudong-bupt/p/9194394.ht ...

  6. C++ 并发编程,std::unique_lock与std::lock_guard区别示例

    背景 平时看代码时,也会使用到std::lock_guard,但是std::unique_lock用的比较少.在看并发编程,这里总结一下.方便后续使用. std::unique_lock也可以提供自动 ...

  7. C++11 std::unique_lock与std::lock_guard区别及多线程应用实例

    C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢导致程序出现未定义的行为.通常的做法是在修改共享数据成员的时候进行加锁--mutex.在使用锁的时候通 ...

  8. std::unique_lock与std::lock_guard分析

    背景 C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢,导致程序出现未定义或异常行为.通常的做法是在修改共享数据成员时进行加锁(mutex).在使用锁 ...

  9. std::unique_lock与std::lock_guard区别示例

    std::lock_guard std::lock_guard<std::mutex> lk(frame_mutex); std::unique_lock<std::mutex> ...

随机推荐

  1. file /usr/share/mysql/charsets/README from install of MySQL-server-5.1.73-1.glibc23.i386 conflicts with file from package mysql-libs-5.1.73-8.el6_8.i686

    1:也许之前的机器安装过Mysql,但是自己不知道,账号密码也忘记了,又执行安装操作,导致Mysql不兼容问题.Linux上安装MySQL时出现不兼容的解决办法,错误如下所示: [root@maste ...

  2. [转] Mongoose初使用总结

    连接mongoose mongoose连接数据库有两种方式 第一种: 'use strict'; const mongoose = require('mongoose'); mongoose.conn ...

  3. 【CF666E】Forensic Examination

    题解: 熟练掌握了后缀自动机后大部分题目应该都比较容易想 首先对t建立广义后缀自动机 然后我们可以用线段树合并处理出每个点每个串出现的次数,然后求出最大值 匹配的时候比较巧妙 我们离线处理 对于同一个 ...

  4. [转]maven全局配置文件settings.xml详解

    概要 settings.xml有什么用? 如果在Eclipse中使用过Maven插件,想必会有这个经验:配置settings.xml文件的路径. Paste_Image.png settings.xm ...

  5. .net core 使用NPOI填充Word模板导出Word

    最近工作用到在Word模板插入数据库数据,导出一个带数据的Word文件,想起来之前操作Word都是用微软提供的Microsoft.Office.Interop.Word,而在最新的..NET CORE ...

  6. awk介绍

    awk 是一个强大的文本处理工具,它将文本逐行读入,并进行切片,默认以空白格为分割符,对单个切片进行分析,处理. 用法: awk '{pattern + action}' {filenames} 尽管 ...

  7. Constructing Roads-最小生成树(kruskal)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1102 题目描述: #include<cstdio> #include<cstring ...

  8. 【python】异步IO

    No1: 协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行. 优势: 1.最大的优势就是协程极高的执行效率.因为子程序切换不是线程切换,而是 ...

  9. Windows10 下Apache服务器搭建

    Windows10 下Apache服务器搭建   转 https://blog.csdn.net/sunqian666888/article/details/78561399 目录 一.软件下载 二. ...

  10. Effective前端1---chapter 2 用CSS画一个三角形

    1.CSS画三角形的画法 第一步:三角形可以用border画出来,首先一个有四个border的div长这样: <div class="triangle"></di ...