程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> c++11多線程庫

c++11多線程庫

編輯:C++入門知識

 

 

標准線程庫,c++11引入,包含原子操作庫、互斥鎖、條件變量。。。

 

 

創建線程的四種方法:

 

1. 通過全局函數創建線程

線程類的構造函數是變參構造函數,第一個參數是線程函數,後面的參數為線程函數的參數(參數通過值傳遞方式,若要引用傳遞須加std::ref())。

thread   t1 (counter, 1, 6);   //void counter(int, int);

 

2. 通過函數對象創建線程

//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,此時只能用第一種構造方式。

 

3. 通過lambda表達式創建線程

目前還沒學習lambda表達式,略過......

 

4. 通過成員函數創建線程

// class Counter  c();

thread   t{&Counter::process, &c};

一般常見的是一個類自己創建一個後台處理線程:thread   t{&Counter::process, this};

 

thread_local    int   n;

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. 互斥體類

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區別同上。

 

2. 鎖類

鎖類是一個包裝器,析構函數會自動釋放關聯的互斥體。

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()運算符。

 

3. 獲得多個互斥體對象上的鎖

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。

 

參數順序每次應保持一致, 否則易死鎖。

 

4. std::call_once         std::once_flag

保證call_once調度的函數只被執行一次。

 

5. 實例:

<mutex>
<timed_mutex> mLock(mTimedMutex, chrono::milliseconds(
<mutex><mutex>
 init() { p =  ();   cout<<<< *  initialized = ( ! initialized)               
<mutex>( ! initialized)         
= <<<<

 

1. std::condition_variable  只能等待unique_lock<mutex>的條件變量

 notify_one();  
 notify_all();    
 wait( unique_lock<mutex>&<mutex>& lk,  chrono::duration<Rep,Period>&<mutex>&lk,  chrono::time_point<Clock,Duration>& abs_time);

2. std::condition_variable_any      支持任何類型的Lock類

3.

std::queue<std::>
unique_lock<mutex>  
unique_lock<mutex>  (
     mCondVar.wait(
}

 

promise/future模型方便獲取線程返回的結果、線程間通信、處理異常

 

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved