voidfunction_1(){ int count = 10; while (count > 0) { std::unique_lock<std::mutex> locker(mu); q.push_front(count); locker.unlock(); std::this_thread::sleep_for(std::chrono::seconds(1)); count--; } }
voidfunction_2(){ int data = 0; while ( data != 1) { std::unique_lock<std::mutex> locker(mu); if (!q.empty()) { data = q.back(); q.pop_back(); locker.unlock(); std::cout << "t2 got a value from t1: " << data << std::endl; } else { locker.unlock(); } } } intmain(){ std::thread t1(function_1); std::thread t2(function_2); t1.join(); t2.join(); return0; }
//输出结果 //t2 got a value from t1: 10 //t2 got a value from t1: 9 //t2 got a value from t1: 8 //t2 got a value from t1: 7 //t2 got a value from t1: 6 //t2 got a value from t1: 5 //t2 got a value from t1: 4 //t2 got a value from t1: 3 //t2 got a value from t1: 2 //t2 got a value from t1: 1
voidfunction_2(){ int data = 0; while ( data != 1) { std::unique_lock<std::mutex> locker(mu); if (!q.empty()) { data = q.back(); q.pop_back(); locker.unlock(); std::cout << "t2 got a value from t1: " << data << std::endl; } else { locker.unlock(); std::this_thread::sleep_for(std::chrono::milliseconds(500)); } } }
voidfunction_1(){ int count = 10; while (count > 0) { std::unique_lock<std::mutex> locker(mu); q.push_front(count); locker.unlock(); cond.notify_one(); // Notify one waiting thread, if there is one. std::this_thread::sleep_for(std::chrono::seconds(1)); count--; } }
voidfunction_2(){ int data = 0; while ( data != 1) { std::unique_lock<std::mutex> locker(mu); while(q.empty()) cond.wait(locker); // Unlock mu and wait to be notified data = q.back(); q.pop_back(); locker.unlock(); std::cout << "t2 got a value from t1: " << data << std::endl; } } intmain(){ std::thread t1(function_1); std::thread t2(function_2); t1.join(); t2.join(); return0; }
voidfunction_2(){ int data = 0; while ( data != 1) { std::unique_lock<std::mutex> locker(mu); cond.wait(locker, [](){ return !q.empty();} ); // Unlock mu and wait to be notified data = q.back(); q.pop_back(); locker.unlock(); std::cout << "t2 got a value from t1: " << data << std::endl; } }
解决这个问题也很简单,使用c++中常见的RAII技术,即**获取资源即初始化(Resource Acquisition Is Initialization)**技术,这是c++中管理资源的常用方式。简单的说就是在类的构造函数中创建资源,在析构函数中释放资源,因为就算发生了异常,c++也能保证类的析构函数能够执行。我们不需要自己写个类包装mutex,c++库已经提供了std::lock_guard类模板,使用方法如下:
classLogFile { std::mutex m_mutex; ofstream f; public: LogFile() { f.open("log.txt"); } ~LogFile() { f.close(); } voidshared_print(string msg, int id){ std::lock_guard<std::mutex> guard(m_mutex); f << msg << id << endl; } // 1.Never return f to the outside world ofstream& getStream(){ return f; //never do this !!! } // 2.Never pass f as an argument to user provided function voidprocess(void fun(ostream&)){ fun(f); } };