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年 ...
随机推荐
- luoguP4721 【模板】分治 FFT
P4721 [模板]分治 FFT 链接 luogu 题目描述 给定长度为 \(n-1\) 的数组 \(g[1],g[2],..,g[n-1]\),求 \(f[0],f[1],..,f[n-1]\),其 ...
- 花了两个星期,我终于把 WSGI 整明白了
在 三百六十行,行行转 IT 的现状下,很多来自各行各业的同学,都选择 Python 这门胶水语言做为踏入互联网大门的第一块敲门砖,在这些人里,又有相当大比例的同学选择了 Web 开发这个方向(包括我 ...
- mac 搭建Java Spring boot 环境(idea)
首先安装插件 安装下面的这个插件 然后重启idea,新建工程 选择新建 Springboot 框架 改写项目名称 选择类型 设置工程名称 删除多余的文件 编译工程 然后运行 1. 2. 参考: htt ...
- [技术博客]使用CDN加快网站访问速度
[技术博客]使用CDN加快网站访问速度 2s : most users are willing to wait 10s : the limit for keeping the user's atten ...
- SpringBoot激活profiles
多环境是最常见的配置隔离方式之一,可以根据不同的运行环境提供不同的配置信息来应对不同的业务场景,在SpringBoot内支持了多种配置隔离的方式,可以激活单个或者多个配置文件. 激活Profiles的 ...
- 深度学习最全优化方法总结比较及在tensorflow实现
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u010899985/article/d ...
- 列出python库的内置方法
import cv dir(cv) ['16SC', '16UC', '32FC', '32SC', '64FC', '8SC', '8UC', 'Abs', 'AbsDiff', 'AbsDiffS ...
- 微信小程序图片宽度100%,高度自适应
实现图片自适应,按照一般情况只需设置: img { width: 100%; height: auto; } 但是微信小程序里是特例,需要image标签上设置属性mode=widthFix,就是hei ...
- 搭建基于 Anaconda 管理的多用户 JupyterHub 平台
搭建基于 Anaconda 管理的多用户 JupyterHub 平台 情况:计算工作站放在实验室,多个同学需要接入使用,且需要各自独立的环境,并使用 Jupyter notebook 平台以方便协作. ...
- 【Python】解析Python中的异常操作
目录结构: contents structure [-] try,except,else,finally块 异常处理 使用except而不带任何异常类型 使用except而带多种异常类型 try-fi ...