創建線程的四種方法:
線程類的構造函數是變參構造函數,第一個參數是線程函數,後面的參數為線程函數的參數(參數通過值傳遞方式,若要引用傳遞須加std::ref())。
thread t1 (counter, 1, 6); //void counter(int, int);
//class Counter 實現 operator()
1) thread t1{Counter(1, 20)}; //c++統一推薦方法
2) Counter c(1, 20);
thread t2(c);
3) thread t3(Counter(1,20));
比較第一種和第三種構造方式,如果函數對象的構造函數不需要任何參數。 thread t3(Counter());是不行的,因為編譯器會認為你在聲明一個函數,函數名為t3,此時只能用第一種構造方式。
目前還沒學習lambda表達式,略過......
// class Counter c();
thread t{&Counter::process, &c};
一般常見的是一個類自己創建一個後台處理線程:thread t{&Counter::process, this};
n作為線程參數傳遞給線程,那麼每個線程有一個n的副本,在線程整個生命周期中存在,且只初始化一次,如同static局部變量。
例如:
int counter = 0;
............
++counter; //因為++counter不時原子操作,多個線程中出現此操作時不是線程安全的。
應該用:
atomic<int> counter(0); //等效於 atomic_int counter(0);
............
++counter; //此時多個線程執行++counter是一個原子操作,是線程安全的。
func( std::atomic<>&( i=; i<; ++++<> counter(<std::thread>( i=; i<; ++ threads.push_back( std::thread{ func, std::( auto& <<<<counter<<
編寫多線程必須分外留意操作順序,如果無法避免線程共享數據,則必須提供同步機制,保證一次只有一個線程能更改數據。使用互斥解決競爭條件,可能導致死鎖。
1) 非定時互斥體類 std::mutex std::recursive_mutex
lock() : 嘗試獲取鎖,並且阻塞直到獲取鎖。
try_lock() : 嘗試獲取鎖,並立即返回,成功獲取返回true,否則false。
unlock() : 釋放鎖。
mutex與recursive_mutex的區別在於,前者已經獲得所後不得再嘗試獲取,這會死鎖,後者能遞歸獲取,注意釋放次數應與獲取次數相等。
2) 定時互斥鎖類 std::timed_mutex std::recursive_timed_mutex
lock() , try_lock() , unlock()
try_lock_for(rel_time) : 指定相對時間內獲得返回true, 超時返回false。
try_lock_until(abs_time) : 指定系統絕對時間內獲得返回true, 超時返回false。
timed_mutex與recursive_timed_mutex區別同上。
鎖類是一個包裝器,析構函數會自動釋放關聯的互斥體。
1) 簡單鎖 std::lock_guard
其構造函數會要求獲得互斥體,並阻塞直到獲得鎖。
2) 復雜鎖 std::unique_lock
explict unique_lock( mutex_type& m); & m, defer_lock_t) noexcept; & m, try_to_lock_t); & m, adopt_lock_t); < Clock, Duration>& m, chrono::time_point<Clock, Duration>& abs_time); < Rep, Period>& m, chrono::duration<Rep, Period>& rel_time);
unique_lock類還支持lock(), try_lock(), try_lock_for(), try_lock_until()等方法。
通過owns_lock()查看是否獲得了這個鎖;也可以用if對unique_lock對象直接判斷是否獲得鎖,因為它定義了bool()運算符。
1) 泛型lock可變參數模板函數
template <class L1, class L2, class...L3>
void lock(L1&, L2&, L3&...);
按順序鎖定,如果一個互斥體拋出異常,會對已獲得的鎖unlock。
2) 泛型try_lock
template <class L1, class L2, class...L3>
int try_lock(L1&, L2&, L3&...);
通過順序調用互斥體對象的try_lock,成功返回-1,失敗返回從0開始的位置索引,並對已獲得的鎖unlock。
參數順序每次應保持一致, 否則易死鎖。
保證call_once調度的函數只被執行一次。
<mutex> <timed_mutex> mLock(mTimedMutex, chrono::milliseconds( <mutex><mutex> init() { p = (); cout<<<< * initialized = ( ! initialized) <mutex>( ! initialized) = <<<<
notify_one(); notify_all(); wait( unique_lock<mutex>&<mutex>& lk, chrono::duration<Rep,Period>&<mutex>&lk, chrono::time_point<Clock,Duration>& abs_time);
std::queue<std::> unique_lock<mutex> unique_lock<mutex> ( mCondVar.wait( }