等待事件或等待其他條件 坐車案例 想象一種情況:假設晚上坐車外出,如何才能確保不坐過站又能使自己最輕鬆? 方法一:不睡覺,時刻關註自己的位置 1 #include <iostream> 2 #include <thread> 3 #include <mutex> 4 using namespace ...
1 #include <iostream> 2 #include <thread> 3 #include <mutex> 4 using namespace std; 5 6 mutex _mtx; 7 bool bFlag = false; 8 void wait_for_flag() 9 { 10 auto startTime = chrono::steady_clock::now(); 11 while (1) 12 { 13 unique_lock<mutex> lock(_mtx); 14 if (bFlag) 15 { 16 auto endTime = chrono::steady_clock::now(); 17 double dCount = chrono::duration<double, std::milli>(endTime - startTime).count(); 18 cout << "wait_for_flag consume : " << dCount << endl; 19 return; 20 } 21 } 22 } 23 24 void set_flag() 25 { 26 auto startTime = chrono::steady_clock::now(); 27 unique_lock<mutex> lock(_mtx); 28 for (int i = 0; i < 5; i++) 29 { 30 lock.unlock(); 31 //do something comsume 1000ms 32 this_thread::sleep_for(chrono::milliseconds(1000)); 33 lock.lock(); 34 } 35 36 bFlag = true; 37 auto endTime = chrono::steady_clock::now(); 38 double dCount = chrono::duration<double, std::milli>(endTime - startTime).count(); 39 cout << "set_flag consume : " << dCount << endl; 40 } 41 42 int main() 43 { 44 thread th1(wait_for_flag); 45 thread th2(set_flag); 46 th1.join(); 47 th2.join(); 48 return 0; 49 }
set_flag consume : 5045.39 wait_for_flag consume : 5045.97
1 void wait_for_flag() 2 { 3 auto startTime = chrono::steady_clock::now(); 4 unique_lock<mutex> lock(_mtx); 5 while (!bFlag) 6 { 7 lock.unlock(); 8 //設置 500ms 的鬧鐘 9 this_thread::sleep_for(chrono::milliseconds(500)); 10 lock.lock(); 11 } 12 13 auto endTime = chrono::steady_clock::now(); 14 double dCount = chrono::duration<double, std::milli>(endTime - startTime).count(); 15 cout << "wait_for_flag consume : " << dCount << endl; 16 }
上面代碼中引用了 this_thread::sleep_for()函數,如果暫時不滿足條件,就讓線程休眠。
set_flag consume : 5061.66 wait_for_flag consume : 5570.77
1 mutex _mtx; 2 bool bFlag = false; 3 condition_variable _cond; //條件變數 4 void wait_for_flag() 5 { 6 auto startTime = chrono::steady_clock::now(); 7 unique_lock<mutex> lock(_mtx); 8 _cond.wait(lock, []() {return bFlag; }); //等待 9 10 auto endTime = chrono::steady_clock::now(); 11 double dCount = chrono::duration<double, std::milli>(endTime - startTime).count(); 12 cout << "wait_for_flag consume : " << dCount << endl; 13 } 14 15 void set_flag() 16 { 17 auto startTime = chrono::steady_clock::now(); 18 unique_lock<mutex> lock(_mtx); 19 for (int i = 0; i < 5; i++) 20 { 21 lock.unlock(); 22 //do something comsume 1000ms 23 this_thread::sleep_for(chrono::milliseconds(1000)); 24 lock.lock(); 25 } 26 27 bFlag = true; 28 _cond.notify_one(); //通知 29 auto endTime = chrono::steady_clock::now(); 30 double dCount = chrono::duration<double, std::milli>(endTime - startTime).count(); 31 cout << "set_flag consume : " << dCount << endl; 32 }
set_flag consume : 5015.84 wait_for_flag consume : 5016.75
condition_variable(); ~condition_variable(); condition_variable(const condition_variable&) = delete; condition_variable& operator=(const condition_variable&) = delete;
void notify_one(); //喚醒一個等待者 void notify_all(); //喚醒所有等待者
void wait(unique_lock<mutex>& _Lck); void wait(unique_lock<mutex>& _Lck, _Predicate _Pred);
參數:
wait
template <class _Rep, class _Period> cv_status wait_for( unique_lock<mutex>& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time); template <class _Rep, class _Period, class _Predicate> bool wait_for( unique_lock<mutex>& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time, _Predicate _Pred);
參數:
wait_
template <class _Clock, class _Duration> cv_status wait_until( unique_lock<mutex>&_Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time); template <class _Clock, class _Duration, class _Predicate> bool wait_until( unique_lock<mutex>&_Lck, const chrono::time_point<_Clock, _Duration>&_Abs_time, _Predicate _Pred);
參數:
返回值:
含義:
condition_variable_any(); ~condition_variable_any(); condition_variable_any(const condition_variable_any&) = delete; condition_variable_any& operator=(const condition_variable_any&) = delete;
void notify_one(); void notify_all();
template <class _Lock> void wait(_Lock& _Lck); template <class _Lock, class _Predicate> void wait(_Lock& _Lck, _Predicate _Pred);
template <class _Lock, class _Rep, class _Period> cv_status wait_for( _Lock & _Lck, const chrono::duration<_Rep, _Period>& _Rel_time); template <class _Lock, class _Rep, class _Period, class _Predicate> bool wait_for( _Lock & _Lck, const chrono::duration<_Rep, _Period>&_Rel_time, _Predicate _Pred);
template <class _Lock, class _Clock, class _Duration> cv_status wait_until(_Lock & _Lck, const chrono::time_point<_Clock, _Duration>&_Abs_time) template <class _Lock, class _Clock, class _Duration, class _Predicate> bool wait_until(_Lock & _Lck, const chrono::time_point<_Clock, _Duration>&_Abs_time, _Predicate _Pred)
1 mutex _mtx; 2 condition_variable _cond; 3 queue<int> _dataQueue; 4 5 void data_preparation_thread() 6 { 7 while (true) 8 { 9 int _data = rand(); 10 { 11 std::lock_guard<mutex> lock(_mtx); 12 _dataQueue.push(_data); 13 } 14 _cond.notify_all(); 15 this_thread::sleep_for(chrono::milliseconds(1000)); 16 } 17 } 18 19 void data_processing_thread() 20 { 21 while (true) 22 { 23 std::unique_lock<mutex> lock(_mtx); 24 _cond.wait(lock, []() 25 { 26 bool bEmpty = _dataQueue.empty(); 27 if (bEmpty) 28 cout << this_thread::get_id() << " be spurious waken up\n"; 29 30 return !bEmpty; 31 }); 32 int _data = _dataQueue.front(); 33 _dataQueue.pop(); 34 lock.unlock(); 35 36 cout << "threadID : " << this_thread::get_id() << " data = " << _data << endl; 37 } 38 } 39 40 int main() 41 { 42 srand(time(NULL)); 43 44 thread th1(data_processing_thread); 45 thread th2(data_processing_thread); 46 thread th3(data_preparation_thread); 47 th1.join(); 48 th2.join(); 49 th3.join(); 50 return 0; 51 }
1 void wait_for_flag() 2 { 3 unique_lock<mutex> lock(_mtx); 4 _cond.wait(lock); //等待 5 } 6 7 void set_flag() 8 { 9 unique_lock<mutex> lock(_mtx); 10 bFlag = true; 11 _cond.notify_one(); //通知 12 } 13 14 int main() 15 { 16 thread th1(set_flag); 17 thread th2(wait_for_flag); 18 th1.join(); 19 th2.join(); 20 return 0; 21 }
future(); ~future(); future(future&& _Other); future& operator=(future&& _Right); future(const future&) = delete; future& operator=(const future&) = delete;
bool valid() const;
template <class _Ty> _Ty get();
void wait() const;
template <class _Rep, class _Per> future_status wait_for(const chrono::duration<_Rep, _Per>& _Rel_time);
template <class _Clock, class _Dur> future_status wait_until(const chrono::time_point<_Clock, _Dur>& _Abs_time);
template <class _Ty> shared_future<_Ty> share();
shared_future(); //構造函數 ~shared_future(); //析構函數 //支持拷貝 shared_future(const shared_future& _Other); shared_future& operator=(const shared_future& _Right); //支持移動 shared_future(future<_Ty>&& _Other); shared_future& operator=(shared_future&& _Right);
bool valid() const;
template <class _Ty> const _Ty& get() const;
void wait() const; template <class _Rep, class _Per> future_status wait_for( const chrono::duration<_Rep, _Per>&_Rel_time); template <class _Clock, class _Dur> future_status wait_until( const chrono::time_point<_Clock, _Dur>& _Abs_time);
1 std::promise<int> pro; 2 std::future<int> _fu = pro.get_future(); 3 std::shared_future<int> _sfu = std::move(_fu); //顯示 4 5 std::promise<int> pro; 6 std::shared_future<int> _sfu = pro.get_future(); //隱式 7 8 std::promise<int> pro; 9 std::future<int> _fu = pro.get_future(); 10 std::shared_future<int> _sfu = _fu.share(); //share函數
template <class _Fty, class... _ArgTypes> std::future<...> async(_Fty&& _Fnarg, _ArgTypes&&... _Args); template <class _Fty, class... _ArgTypes> std::future<...> async(launch _Policy, _Fty&& _Fnarg, _ArgTypes&&... _Args);
//省略Res_Data類 int Entry(Res_Data data) { cout << "-----------"; return 5; } int main() { Res_Data _data; auto _fu = std::async(Entry, _data); cout << _fu.get() << endl; return 0; }
輸出如下:
008FF9E3 Constractor 008FF6E8 Copy Constractor 008FF33C Move Constractor 00CE0854 Move Constractor 008FF33C Destractor 008FF6E8 Destractor 009FDE74 Move Constractor ----------- 009FDE74 Destractor 00CE0854 Destractor 5 008FF9E3 Destractor
int ThreadEntry() { cout << "son threadId : " << std::this_thread::get_id() << " start to do something!" << endl; std::this_thread::sleep_for(std::chrono::milliseconds(5000)); cout << "son threadId : " << std::this_thread::get_id() << " end doing something!" << endl; return 5; } int