第三章 数据竞争与互斥对象
2016-08-17 09:08
381 查看
案例:
输出
可以看到其中有Fromt1:From main:50
原因在于代码中的cout为两个线程共同竞争使用。解决的方法使用互斥对象来同步资源访问。
但是,这样使用下,有一种情况发生时将会造成死锁的发生。
在程序mu.lock与mu.unlock之间的函数如果抛出意外,此事程序将不能解锁,从而使得程序锁住。
使用另外一种方式来替代:
Std::lock_guard<std::mutex>guard(mu)
#end
另外一个问题来了,cout是全局型的,因此其他程序段可以继续使用cout,从而没有实现完全意义上的线程保护,。即没有在互斥量mu中作为私有函数供(绑定)使用。
使用类可以解决该问题。
找到文件夹下的文件
清单3.2 无意中传递了保护数据的引用
例子中process_data看起来没有任何问题,
std::lock_guard 对数据做了很好的保护,但调用用户提供的函数func①,就意味着foo能够绕过保护机制将函数
malicious_function 传递进去②,在没有锁定互斥量的情况下调用do_something()
#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(); } |
另外一个问题来了,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()
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Python3写爬虫(四)多线程实现数据爬取
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- C#实现多线程的同步方法实例分析
- C#线程间不能调用剪切板的解决方法
- Lua中调用C++函数示例
- 浅谈chuck-lua中的多线程
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#多线程编程中的锁系统(三)
- C#线程同步的三类情景分析
- C#获取进程或线程相关信息的方法
- 简单对比C#程序中的单线程与多线程设计
- C#停止线程的方法
- 解析C#多线程编程中异步多线程的实现及线程池的使用