C++ 11 多线程下std::unique_lock与std::lock_guard的区别和用法
这里主要介绍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的区别和用法的更多相关文章
- C++11 std::unique_lock与std::lock_guard区别及多线程应用实例
C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢导致程序出现未定义的行为.通常的做法是在修改共享数据成员的时候进行加锁--mutex.在使用锁的时候通 ...
- std::unique_lock与std::lock_guard分析
背景 C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢,导致程序出现未定义或异常行为.通常的做法是在修改共享数据成员时进行加锁(mutex).在使用锁 ...
- boost::unique_lock和boost::lock_guard的区别
lock_guard unique_lock boost::mutex mutex; boost::unique_lock<boost::mutex> lock(mutex); std:: ...
- C++11 多线程编程 使用lambda创建std::thread (生产/消费者模式)
要写个tcp server / client的博客,想着先写个c++11多线程程序.方便后面写博客使用. 目前c++11中写多线程已经很方便了,不用再像之前的pthread_create,c++11中 ...
- C++11 并发指南九(综合运用: C++11 多线程下生产者消费者模型详解)
前面八章介绍了 C++11 并发编程的基础(抱歉哈,第五章-第八章还在草稿中),本文将综合运用 C++11 中的新的基础设施(主要是多线程.锁.条件变量)来阐述一个经典问题——生产者消费者模型,并给出 ...
- 综合运用: C++11 多线程下生产者消费者模型详解(转)
生产者消费者问题是多线程并发中一个非常经典的问题,相信学过操作系统课程的同学都清楚这个问题的根源.本文将就四种情况分析并介绍生产者和消费者问题,它们分别是:单生产者-单消费者模型,单生产者-多消费者模 ...
- C++ 并发编程,std::unique_lock与std::lock_guard区别示例
背景 平时看代码时,也会使用到std::lock_guard,但是std::unique_lock用的比较少.在看并发编程,这里总结一下.方便后续使用. std::unique_lock也可以提供自动 ...
- std::unique_lock与std::lock_guard区别示例
std::lock_guard std::lock_guard<std::mutex> lk(frame_mutex); std::unique_lock<std::mutex> ...
- 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 ...
随机推荐
- mina websocket 粘包、断包、(丢包)解决心得
被这3个(其实是2个)问题坑惨了,目前没发现存在丢包问题,之前认为的丢包问题事实是不存在的. 粘包和断包的情况是存在的,这两个问题不怕,只要发送接收到的数据包顺序没有被打乱颠倒,一切都好办. 容易掉的 ...
- 谈谈tmpdir与innodb_tmpdir的区别和用处
[背景] innodb_tmpdir是在innodb online ddl中提到的一个参数:大致的意思是innodb在做online-ddl的时候会向临时目录写入“临时排序文件” 而这些文件的大小基本 ...
- django项目添加utf-8编码支持中文
代码中出现中文会报错: Non-ASCII character '...' in file ......models.py on line ......., but no encoding decla ...
- 基于vue-cli配置手淘的lib-flexible + rem,实现移动端自适应
没接触过flexible的建议先看看大漠的这篇文章这样你才会知道长度为什么用rem,而字体要用px 安装flexible npm install lib-flexible --save 引入flexi ...
- 基于Vue element-ui实现支持多级纵向动态表头的仿表格布局
[本文出自天外归云的博客园] 需求图示如下,多级纵向动态表头表格: 我的思路是用element-ui的layout实现,做出一个仿造表格,能够支持动态的.多级的.纵向的表头: <template ...
- 【GMT43智能液晶模块】例程十:DMA实验——存储器到存储器的传输
实验原理: DMA(直接存储器访问)传输不需要占用CPU,可以在存储器至存储器实现高速的数据 传输.本实验采用DMA2控制器的数据流0,选用通道0进行数据传输.通过液晶控制传输 和结果显示. 示例截图 ...
- centos7修改系统时间、时区
直接用下面命令直接更换时区 cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
- oracle获取过去两年的今天时间
获取过去两年的今天时间: SELECT last_day(ADD_MONTHS(ADD_MONTHS(sysdate,-12), ROWNUM - 1)) as monthlist FROM DUAL ...
- C++中常用的std标准容器
从c++11标准以来,c++中std定义的几种容器的效率非常高,优化的非常好,完全没有必要自己去定义类似的数据结构.了解使用它们,可以满足90%的日常编程需要.该篇文章基于c++11标准,从用户角度来 ...
- ubuntu下core file文件生成及调试
1.简介:corefile 是Linux下程序崩溃时生成的文件,可以用来分析程序崩溃的原因,因为它内部包含了程序崩溃时的堆栈信息. 2.corefile的设置 默认情况下,程序崩溃是不会生成coref ...