c++11多线程记录3: 数据争用和Mutex的使用
https://www.youtube.com/watch?v=3ZxZPeXPaM4 学习视频
数据争用
简单来说就是存在多个线程同时对某个共同的对象进行读写(至少有一个线程在做写操作),造成读取这个对象时的结果不可预测
如下
int num = 0;
void func(int &v)
{
for (int i = 0; i < 100000; ++i)
{
num = num + 1;
v++;
}
}
int main()
{
int v = 0;
std::vector<std::thread> ts;
for (int i = 0; i < 100; ++i)
{
ts.push_back(std::thread(func, std::ref(v)));
}
for (int i = 0; i < 100; ++i)
{
ts[i].join();
}
std::cout << num << ", " << v << std::endl;
return 0;
}
cout结果并不是10 000 000, 10 000 000
使用Mutex控制对象的读写
在对象的读写操作之前调用mutex::lock即可(记得不需要持有对象时调用mutex::unlock)
...
std::mutex mu;
void func()
{
...
mu.lock();
num += 1;
v += 1;
mu.unlock();
}
...
std::lock_guard
在mutex的lock-unlock块里如果抛出异常,那么unlock就不会被调用(或者忘记调用unlock也是有可能的),
这时可以考虑使用lock_guard:
...
{
std::lock_guard<std::mutex> guard(mu);
v++;
num++;
}
...
我感觉应该是lock_guard内部将会持有mutex,然后在析构函数里尝试调用mutex的unlock方法
读写控制的对象有没有完全被锁定
针对上面的例子,有一个全局变量num,和一个局部变量v,虽然在各个子线程里都用mutex进行了读写控制;
但是在主线程里并没有,仍然可以在main里面随意的处理这两个共享对象;
处理方法就是将要保护的资源对象和mutex绑定在一起,保证每次使用资源对象前必须通过mutex
如下:
class LogFile {
std::mutex m_mutex;
ofstream f;
LogFile() {
f.open(...);
}
void shared_print(string id, int value) {
std::lock_guard<mutex> guard(m_mutex);
f << id << ", " << value << endl;
}
// ofstream &getStream() { return f; }
}
上面这个例子,切记不能将LogFile的f对象暴露出来,就像最后一行注释那样
当然如果返回的是ofstream是没问题的;
还有一些其它情况可能“意外”暴露LogFile::f,如下:
void LogFile::processf(void fun(ofstream&))
{
fun(this->f);
}
这里就“不小心”将f对象引用传递给了某个函数fun,在fun里,LogFile::f就失去了mutex的保护
小结
- 使用mutex来控制资源对象的读写
- 不要将内部资源对象暴露出Wrapper类
- 注意接口设计的合理性
c++11多线程记录3: 数据争用和Mutex的使用的更多相关文章
- c++11多线程记录2:线程管理
线程没有调用join和detach thread对象必须调用join或者detach,否则程序会终止 例如: void func() { std::cout << "hello, ...
- c++11多线程记录0
两种并发编程模型 多进程 进程间通信常用的几种方式: 文件 管道 消息队列 多线程 一个进程中存在的多个线程,通常通过共享内存来通信,(说的非常非常粗俗,就是通过类似"全局变量"的 ...
- c++11多线程记录6:条件变量(condition variables)
https://www.youtube.com/watch?v=13dFggo4t_I视频地址 实例1 考虑这样一个场景:存在一个全局队列deque,线程A向deque中推入数据(写),线程B从deq ...
- c++11多线程记录5: Unique Lock和延时初始化
https://www.youtube.com/user/BoQianTheProgrammer 视频网址 Unique Lock unique_lock和lock_guard类似,都是mutex的w ...
- c++11多线程记录4:死锁
简单示例 举个例子,桌上有一支笔和一张纸,小A和小B都要拿到纸笔写字 小A拿了笔,小B拿了纸,这时就形成了死锁(两人都不愿意让出纸笔). 其实只要稍加控制就可以避免这种情况:规定必须先拿到纸再能去尝试 ...
- 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多线程教学(一)
本篇教学代码可在GitHub获得:https://github.com/sol-prog/threads. 在之前的教学中,我展示了一些最新进的C++11语言内容: 1. 正则表达式(http://s ...
- C# 实现的多线程异步Socket数据包接收器框架
转载自Csdn : http://blog.csdn.net/jubao_liang/article/details/4005438 几天前在博问中看到一个C# Socket问题,就想到笔者2004年 ...
随机推荐
- 在WinDbg中调试时如何查看类/结构对象成员的值
有时,当您调试应用程序时,会碰巧得到指向类的指针,该类只有几个成员变量,包括结构和其他类对象!如何看待内部类/结构变量成员的值??所以,这是提示.下面是用于演示命令的代码. struct testSt ...
- kafk设计要点
kafka的设计目标是高吞吐量,所以kafka自己设计了一套高性能但是不通用的协议,他是仿照AMQP( Advanced Message Queuing Protocol 高级消息队列协议)设计的 ...
- 2019 SDN课程阅读作业(2)
1.过去20年中可编程网络的发展可以分为几个阶段?每个阶段的贡献是什么? 主动网络(从1990年代中期到2000年代初) 它在网络中引入了可编程的功能以实现更多的创新: 20世纪90年代初,主动网络研 ...
- 论文阅读:Single Image Dehazing via Conditional Generative Adversarial Network
Single Image Dehazing via Conditional Generative Adversarial Network Runde Li∗ Jinshan Pan∗ Zechao L ...
- R语言 rds文件 和 文本文件 转换
library(data.table) ## 读取 rds 文件,然后保存为文本文件 data <- readRDS("pneumonia_pathogens.rds") w ...
- js之切换全屏和退出全屏实现
应用场景:比如很多网页游戏全屏之类的,或者是网上看小说等. 核心代码: //控制全屏 function enterfullscreen() { //进入全屏 $("#fullscreen&q ...
- js操作表格、table、
js添加一行.删除一行 let str="<tr>" +"<td>"+a[1]+"</td>" +&qu ...
- [原创]STAR法则
[原创]STAR法则 STAR法则是情境(situation).任务(task).行动(action).结果(result)四项的缩写. STAR法则是一种常常被面试官使用的工具,用来收集面试者与工作 ...
- iptables 限制端口
限制端口 #!/bin/bashiptables -P INPUT ACCEPTiptables -P OUTPUT ACCEPTiptables -Fiptables -P INPUT DROPip ...
- [Gamma阶段]第七次Scrum Meeting
Scrum Meeting博客目录 [Gamma阶段]第七次Scrum Meeting 基本信息 名称 时间 地点 时长 第七次Scrum Meeting 19/06/3 大运村寝室6楼 25min ...