第三章 数据竞争与互斥对象
来源:互联网 发布:王思聪雪梨的淘宝店铺 编辑:程序博客网 时间:2024/05/16 17:38
案例:
#include<iostream>
#include<string>
#include<thread>
using namespace std;
void function_1()
{
for (int i = 0; i > -100; i--)
{
std::cout << "From t1:" << i << std::endl;
}
}
int main()
{
thread t1(function_1);
for (int i = 0; i < 100; i++)
{
cout << "From main:" << i << endl;
}
t1.join();
}
输出
可以看到其中有Fromt1:From main:50
原因在于代码中的cout为两个线程共同竞争使用。解决的方法使用互斥对象来同步资源访问。
#include<iostream>
#include<string>
#include<thread>
#include<mutex>
using namespace std;
std::mutex mu;
void shared_Print(string msg,int id)
{
mu.lock();
std::cout << msg << id << endl;
mu.unlock();
}
void function_1()
{
for (int i = 0; i > -100; i--)
{
//std::cout << "From t1:" << i << std::endl;
//using shared_Print function instead of function_1
shared_Print("From t1", i);
}
}
int main()
{
thread t1(function_1);
for (int i = 0; i < 100; i++)
{
//cout << "From main:" << i << endl;
shared_Print("From Main()", i);
}
t1.join();
}
但是,这样使用下,有一种情况发生时将会造成死锁的发生。
在程序mu.lock与mu.unlock之间的函数如果抛出意外,此事程序将不能解锁,从而使得程序锁住。
使用另外一种方式来替代:
Std::lock_guard<std::mutex>guard(mu)
#include<iostream>
#include<string>
#include<thread>
#include<mutex>
using namespace std;
std::mutex mu;
void shared_Print(string msg,int id)
{
std::lock_guard<std::mutex> guard(mu);
std::cout << msg << id << endl;
}
void function_1()
{
for (int i = 0; i > -100; i--)
{
//std::cout << "From t1:" << i << std::endl;
//using shared_Print function instead of function_1
shared_Print("From t1", i);
}
}
int main()
{
thread t1(function_1);
for (int i = 0; i < 100; i++)
{
//cout << "From main:" << i << endl;
shared_Print("From Main()", i);
}
t1.join();
}
#end
另外一个问题来了,cout是全局型的,因此其他程序段可以继续使用cout,从而没有实现完全意义上的线程保护,。即没有在互斥量mu中作为私有函数供(绑定)使用。
使用类可以解决该问题。
#include<iostream>
#include<string>
#include<thread>
#include<mutex>
#include<fstream> //将数据保存到文件中使用fsteam头文件
using namespace std;
std::mutex mu;
class lofFile
{
public:
lofFile() //
{
f.open("log.txt");
}
void share_Print(std::string id, int value) //成员函数
{
std::lock_guard<mutex> locker(m_mutex);
f << "from " << id << value << endl;
}
protected:
private:
mutex m_mutex;
ofstream f;
};
void function_1(lofFile& l) //添加引用
{
for (int i = 0; i > -100; i--)
{
//std::cout << "From t1:" << i << std::endl;
//using shared_Print function instead of function_1
l.share_Print("From t1", i);
}
}
int main()
{
lofFile l;
thread t1(function_1, std::ref(l)); //一定注意添加引用
for (int i = 0; i < 100; i++)
{
//cout << "From main:" << i << endl;
l.share_Print("From Main()", i);
}
t1.join();
}
找到文件夹下的文件
清单3.2 无意中传递了保护数据的引用
class some_data
{
int a;
std::string b;
public:
void do_something();
};
class data_wrapper
{ private:
some_data data;
std::mutex m;
public:
template<typename Function>
void process_data(Function func)
{
std::lock_guard<std::mutex> l(m);
func(data); // 1 传递"保护"数据给用户函数
}
};
some_data* unprotected;
void malicious_function(some_data& protected_data)
{
unprotected=&protected_data;
}
data_wrapper x;
void foo()
{
x.process_data(malicious_function); // 2 传递一个恶意函数
unprotected->do_something(); // 3 在无保护的情况下访问保护数据
}
例子中process_data看起来没有任何问题, std::lock_guard 对数据做了很好的保护,但调用用户提供的函数func①,就意味着foo能够绕过保护机制将函数malicious_function 传递进去②,在没有锁定互斥量的情况下调用do_something()
- 第三章 数据竞争与互斥对象
- 多线程学习之数据竞争与互斥对象
- 竞争条件与互斥
- 多线程与互斥对象
- java资源竞争问题(线程互斥)
- java资源竞争问题(线程互斥)
- 进程间通信(一):竞争条件与互斥方案
- 共享变量与数据竞争
- Mutex与Semaphore 第三部分:互斥的问题
- 互斥对象与临界区对象的区别
- 互斥对象与事件对象实现线程同步
- 互斥对象、事件对象与关键代码段
- 内核中的竞争状态和互斥(简述)
- 第三章 对象与JSON
- 第三章类与对象
- 第三章 类与对象
- 第三章 类与对象
- 创建互斥对象
- C++ primer plus读书笔记(一)
- jee、spring、spring mvc、mybatis 学习(八)
- WPF 串口助手
- ipmsg365src 问题修复
- ScrollView嵌套GridView,加载完成后默认不显示顶部
- 第三章 数据竞争与互斥对象
- MYSQL删除表的记录后如何使ID从1开始
- jenkisn 结合maven+svn部署web应该到tomcat
- Inflater—— LayoutInflater和findViewById()
- AD10 元器件库和封装库的说明(标准封装的尺寸 三极管的封装 封装名后L M N的含义 PCB封装中的紫线的意思)
- 第四章 死锁
- 关于Xcode 7.3 7.3.1 断点 卡死 无限菊花
- linux 查看文件夹大小命令(du)
- Otsu算法