这里主要介绍std::unique_lock与std::lock_guard的区别用法

先说简单的

一、std::lock_guard的用法

std::lock_guard其实就是简单的RAII封装,在构造函数中进行加锁,析构函数中进行解锁,这样可以保证函数退出时,锁一定被释放。

简单来说,就是防止开发者粗心大意,函数在分支中return时,忘记unlock操作导致后续操作全部被挂起甚至引发死锁情况的。

用法如下:

// lock_guard example
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::lock_guard
#include <stdexcept> // std::logic_error std::mutex mtx; void print_even (int x) {
if (x%==) std::cout << x << " is even\n";
else throw (std::logic_error("not even"));
} void print_thread_id (int id) {
try {
// using a local lock_guard to lock mtx guarantees unlocking on destruction / exception:
std::lock_guard<std::mutex> lck (mtx);
print_even(id);
}
catch (std::logic_error&) {
std::cout << "[exception caught]\n";
}
} int main ()
{
std::thread threads[];
// spawn 10 threads:
for (int i=; i<; ++i)
threads[i] = std::thread(print_thread_id,i+); for (auto& th : threads) th.join(); return ;
}

二、std::unique_lock的用法

std::unique_lock的功能相比std::lock_guard来说,就强大多了,是std::lock_guard的功能超集, 封装了各种加锁操作,阻塞的,非阻塞的,还可以结合条件变量一起使用,基本上对锁的各种操作都封装了,当然了,功能丰富是有代价的,那就是性能和内存开销都比std::lock_guard大得多,所以,需要有选择地使用。

std::unique_lock也会在析构的时候自动解锁,所以说,是std::lock_guard的功能超集。

看看std::unique_lock的构造函数,支持三种加锁模式:

unique_lock( mutex_type& m, std::defer_lock_t t );   //延迟加锁
unique_lock( mutex_type& m, std::try_to_lock_t t ); //尝试加锁
unique_lock( mutex_type& m, std::adopt_lock_t t );  //马上加锁

几个主要操作函数:

lock()         //阻塞等待加锁
try_lock()   // 非阻塞等待加锁
try_lock_for()  //在一段时间内尝试加锁
try_lock_until()  //在某个时间点之前尝试加锁

接下来,给个例子:

#include <mutex>
#include <thread>
#include <iostream>
#include <vector>
#include <chrono> int main()
{
int counter = ;
std::mutex counter_mutex;
std::vector<std::thread> threads; auto worker_task = [&](int id) {
std::unique_lock<std::mutex> lock(counter_mutex);
++counter;
std::cout << id << ", initial counter: " << counter << '\n';
lock.unlock(); // don't hold the lock while we simulate an expensive operation
std::this_thread::sleep_for(std::chrono::seconds()); lock.lock();
++counter;
std::cout << id << ", final counter: " << counter << '\n';
}; for (int i = ; i < ; ++i) threads.emplace_back(worker_task, i); for (auto &thread : threads) thread.join();
}

Output:

0, initial counter: 1
1, initial counter: 2
2, initial counter: 3
3, initial counter: 4
4, initial counter: 5
5, initial counter: 6
6, initial counter: 7
7, initial counter: 8
8, initial counter: 9
9, initial counter: 10
6, final counter: 11
3, final counter: 12
4, final counter: 13
2, final counter: 14
5, final counter: 15
0, final counter: 16
1, final counter: 17
7, final counter: 18
9, final counter: 19
8, final counter: 20

C++ 11 多线程下std::unique_lock与std::lock_guard的区别和用法的更多相关文章

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

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

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

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

  3. boost::unique_lock和boost::lock_guard的区别

    lock_guard unique_lock boost::mutex mutex; boost::unique_lock<boost::mutex> lock(mutex); std:: ...

  4. C++11 多线程编程 使用lambda创建std::thread (生产/消费者模式)

    要写个tcp server / client的博客,想着先写个c++11多线程程序.方便后面写博客使用. 目前c++11中写多线程已经很方便了,不用再像之前的pthread_create,c++11中 ...

  5. C++11 并发指南九(综合运用: C++11 多线程下生产者消费者模型详解)

    前面八章介绍了 C++11 并发编程的基础(抱歉哈,第五章-第八章还在草稿中),本文将综合运用 C++11 中的新的基础设施(主要是多线程.锁.条件变量)来阐述一个经典问题——生产者消费者模型,并给出 ...

  6. 综合运用: C++11 多线程下生产者消费者模型详解(转)

    生产者消费者问题是多线程并发中一个非常经典的问题,相信学过操作系统课程的同学都清楚这个问题的根源.本文将就四种情况分析并介绍生产者和消费者问题,它们分别是:单生产者-单消费者模型,单生产者-多消费者模 ...

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

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

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

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

  9. 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 ...

随机推荐

  1. ubuntu intel网卡驱动安装(华硕B250F GAMING主板 )

    jikexianfeng@jikexianfeng:~$ sudo sudo lspci -knn :]: Intel Corporation Device [:591f] (rev ) Subsys ...

  2. java中random()函数用法介绍

    Random() 创建一个新的随机数生成器.  代码如下 复制代码 Random(long seed) 使用单个 long 种子创建一个新的随机数生成器. 我们可以在构造Random对象的时候指定种子 ...

  3. CentOS 7.4nginx配置SSL

    一.在/etc/nginx/conf.d目录下创建虚拟主机配置文件 server { listen 80; server_name www.xx.com xx.com; return 301 http ...

  4. VNC Viewer 设置屏幕分辨率

    1.第一种方法:使用geometry参数进行调整 vncserver -geometry 1280x1024即可,之后通过window下vnc连接后的ubuntu分辨率即为1280x1024了,注意这 ...

  5. Asp.Net Newtonsoft.Json使用教程

    json序列化和反序列化的使用教程 实体 public class wendaModel { private string _title; private string _cons; public s ...

  6. [Java并发编程(三)] Java volatile 关键字介绍

    [Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...

  7. 手动安装mysql

    需要在本机(mac)上装个mysql,看到压缩版的体积最小,结果进入了手工安装的坑(正常有界面可以安装,但安装目录将是/usr/local/mysql),既然入了坑就填上吧. 1.解压到自己选择的目录 ...

  8. 在Linux添加定时任务删除5天前的日志文件

    利用shell脚本自动清理,脚本如下 1.删除文件命令: find 对应目录 -mtime +天数 -name "文件名" -exec rm -rf {} \; 实例命令: fin ...

  9. python 文档

    python 文档 https://docs.python.org/2/library/index.html

  10. MyBatis Plus:No qualifying bean of type 'com.baomidou.mybatisplus.mapper.BaseMapper<?>' available: expected single matching bean but found 4

    场景: 应用MyBatis Plus 和通用Mapper 继承自ServiceImpl实现对Service里的方法进行包装再处理. public interface IServiceBase2< ...