c++11の数据竞争和互斥对象
一、数据竞争的产生
在下面例子中:
void function_1() { for (int i = 0; i < 100; i++) { std::cout << "from function 1:" << i << std::endl; } } int main() { std::thread t(function_1); for (int i = 0; i < 100; i++) { std::cout << "from function main:"<<i<<std::endl; } t.join(); std::getchar(); return 0; }
我们发现其输出的毫无规律,因为主线程和子线程同时调用cout对象造成的,产生了数据竞争
二、互斥对象
上面的问题可以通过互斥对象来解决
#include "stdafx.h" #include <iostream> #include <thread> #include <mutex> #include <string> using namespace std; std::mutex mu; void share_print(std::string msg,int id) { mu.lock(); cout << msg << id << endl; mu.unlock(); } void function_1() { for (int i = 0; i < 100; i++) { share_print("from function 1:",i); } } int main() { std::thread t(function_1); for (int i = 0; i < 100; i++) { share_print("from main:", i); } t.join(); std::getchar(); return 0; }
但是如果cout中发现异常,那么程序将被永远锁住,除非能够保证要锁住的对象不会出现问题,有此引出一下方法
void share_print(std::string msg,int id) { std::lock_guard<std::mutex> gard(mu); cout << msg << id << endl; }
此类并不能阻止其他线程调用cout
三、LogfFile类
class LogfFile { public: LogfFile() { f.open("log.txt"); } void share_print(std::string msg, int id) { std::lock_guard<std::mutex> gard(m_mutex); f << msg << id << endl; } private: std::mutex m_mutex; std::ofstream f; }; void function_1(LogfFile & log) { for (int i = 0; i < 100; i++) { log.share_print("from function 1:",i); } } int main() { LogfFile log; std::thread t(function_1,ref(log)); for (int i = 0; i < 100; i++) { log.share_print("from main:", i); } t.join(); std::getchar(); return 0; }
注意f不能对外开放