c++11多线程记录5: Unique Lock和延时初始化
https://www.youtube.com/user/BoQianTheProgrammer 视频网址
Unique Lock
unique_lock和lock_guard类似,都是mutex的wrapper类,但是前者更加灵活
- lock_guard没有unlock方法,unique_lock可以调用unlock
- unique_lock可以延时调用lock方法,lock_guard不行
- unique_lock不可复制、可移动,lock_guard不可复制、不可移动
// 1
...
std::unique_lock<std::mutex> locker(mu);
g_num ++;
locker.unlock();
...
// 2
...
std::unique_lock<std::mutex> locker(mu, std::defer_lock);
...
locker.lock();
g_num++;
locker.unlock();
...
locker.lock();
g_num++;
locker.unlock();
...
// 3
...
std::unique_lock<std::mutex> locker2 = std::move(locker);
unique_lock并不能取代lock_guard
unique_lock的灵活性是有代价的,灵活的同时其本身所占空间也越大(时间性能上不了解)
有时候并不需要unique_lock的那些灵活性,只要用lock_guard即可
Lasy Initialization
先看下面一段代码
class LogFile {
std::mutex _mu;
ofstream _f;
public:
LogFile() {
_f.open("log.txt");
}
void func(string id, int v) {
std::unique_lock<mutex> locker(_mu);
_f << id << ", " << v << endl;
}
}
打印日志的类,在构造函数里打开log.txt
但是有可能自始至终都没有打印过日志(调用func),那么_f.open就没有必要调用
可以考虑在func中调用_f.open,如下
class LogFile {
std::mutex _mu;
ofstream _f;
public:
LogFile() {
// _f.open("log.txt");
}
void func(string id, int v) {
if (!_f.is_open()) {
_f.open("log.txt");
}
std::unique_lock<mutex> locker(_mu);
_f << id << ", " << v << endl;
}
}
线程安全
这时就要考虑LogFile::func的线程安全问题(针对资源对象_f)),按照前面的方法,通过mutex来控制_f的使用
class LogFile {
std::mutex _mu_open;
ofstream _f;
public:
LogFile() { }
void func(string id, int v) {
if (!_f.is_open()) {
std::unique_lock<mutex> locker(_mu_open);
_f.open("log.txt");
}
...
}
}
上面这段代码并没有做到线程安全。场景假设:
线程A和线程B同时进到 if (_f.is_open())
,这时文件并没有打开过,所以都通过了if判断,
接着A,B都会调用获取mutex,假设A先获取,然后A调用open打开文件,然后释放mutex,
接着B就会获取mutex,然后会再调用一次open。
两次打开一个文件!
不仅仅_f.open需要同步,_f.is_open也需要同步:
...
std::unique_lock<mutex> locker2(_mu_open);
if (_f.is_open()) {
_f.open("log.txt");
}
locker2.unlock();
...
但是这时又会有另外一个问题,每次func函数被调用时都会有一次mutex获取的行为,一定程度上会影响程序的并发性
std::once_flag和std::call_once
针对上面那个问题,c++提供了std::once_flag来解决:
class LogFile {
std::once_flag _flag;
ofstream _f;
public:
LogFile() { }
void func(string id, int v) {
std::call_once(_flag, [&](){_f.open("log.txt");});
...
}
}
上面代码里的lambda函数仅会被一个线程调用一次!
c++11多线程记录5: Unique Lock和延时初始化的更多相关文章
- c++11多线程记录0
两种并发编程模型 多进程 进程间通信常用的几种方式: 文件 管道 消息队列 多线程 一个进程中存在的多个线程,通常通过共享内存来通信,(说的非常非常粗俗,就是通过类似"全局变量"的 ...
- c++11多线程记录6:条件变量(condition variables)
https://www.youtube.com/watch?v=13dFggo4t_I视频地址 实例1 考虑这样一个场景:存在一个全局队列deque,线程A向deque中推入数据(写),线程B从deq ...
- c++11多线程记录4:死锁
简单示例 举个例子,桌上有一支笔和一张纸,小A和小B都要拿到纸笔写字 小A拿了笔,小B拿了纸,这时就形成了死锁(两人都不愿意让出纸笔). 其实只要稍加控制就可以避免这种情况:规定必须先拿到纸再能去尝试 ...
- c++11多线程记录3: 数据争用和Mutex的使用
https://www.youtube.com/watch?v=3ZxZPeXPaM4 学习视频 数据争用 简单来说就是存在多个线程同时对某个共同的对象进行读写(至少有一个线程在做写操作),造成读取这 ...
- c++11多线程记录2:线程管理
线程没有调用join和detach thread对象必须调用join或者detach,否则程序会终止 例如: void func() { std::cout << "hello, ...
- c++11多线程记录1 -- std::thread
启动一个线程 话不多说,直接上代码 void func(); int main() { std::thread t(func); //这里就开始启动线程了 t.join(); // 必须调用join或 ...
- c++11 多线程 -- 基本使用
c++11 多线程 – 基本使用 前言:这篇文章仅针对没有使用过c++11线程库的童鞋来高速入门,也是自己的一个简单记录,内容比較基础. 1.线程的基本使用 2.相互排斥量 3.条件变量 4.原子变量 ...
- 【转】C++ 11 并发指南一(C++ 11 多线程初探)
引言 C++ 11自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些C++ 11的新特性,算是记录一下自己学到的东西吧,和大家共勉. 相信Linux程序员都用过Pthrea ...
- C++11 并发指南一(C++11 多线程初探)
引言 C++11 自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些 C++11 的新特性,今后几篇博客我都会写一些关于 C++11 的特性,算是记录一下自己学到的东西吧, ...
随机推荐
- Linux 检测 tls
检测 tls # openssl s_client -connect intl.jdair.net: -tls1
- 鸿蒙OS与微内核
目前主流面向个人端操作系统都不是像鸿蒙一样采用微内核的,或许在这些操作系统上诞生时面对的需求场景用微内核是行不通的.但在当前场景下是不是能走通要实际验证才知道.面对当前操作系统已成熟的市场生态.专利技 ...
- 第03组 Alpha事后诸葛亮
组长博客 项目Postmortem模板 设想和目标 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们软件要解决的的问题是福州大学校园二手书的处理问题.应该定 ...
- 2019 第二届 科成安洵杯 官方WriteUp -17网安
长文预警:对应源码请加企鹅群获取:861677907 0x01 WEB 1.1 勇闯贪吃蛇大冒险 一进去就看出来是一道web页面JS的小游戏,提示说输入CDUESTC CTF即可闯关成功,但是存在着d ...
- 【BIEE】导出大量数据报错处理请求时出现致命错误。服务器响应为 com.siebel.analytics.utils.InputStreamWithLimit$ReadOverTheLimitException
问题描述 在使用BIEE导出大量数据的时候,报错如下: 处理请求时出现致命错误.服务器响应为: com.siebel.analytics.utils.InputStreamWithLimit$Read ...
- bzoj4868 期末考试 题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4868 显然我们只关注最后出分的学科. 刚开始想的是dp,然而不知道如何记录状态. 突然就想到了正解 ...
- Android Studio 之 ViewModel
ViewModel 是 JetPack 类库中的一个功能,可以保存控件的状态 ,在整个Activity 生命周期中,状态不会失效 如屏幕翻转时,状态可保留,不会失效! 与 LiveData 配合使用! ...
- 如何去掉word中英文单词下的红色波浪线
文件 ->选项 ->校对 在 只隐藏此文档中的拼写错误(S) 选项前打钩,点击确定即可
- 冰多多团队-第五次Scrum会议
冰多多团队-第五次Scrum会议 工作情况 团队成员 已完成任务 待完成任务 zpj 部分Action整合, 接入语音接口,整合项目解决兼容性问题 ASR bug修复 牛雅哲 跑通了科大讯飞语法识别的 ...
- [技术博客]基于动态继承类、WebDriver的浏览器兼容性测试框架搭建
问题背景 观察使用selenium进行自动化测试的过程,我们可以将它概述为: 启动测试进程,在该进程中构建WebDriver 启动浏览器进程,将它与WebDriver建立连接 使用WebDriver向 ...