c 多執行緒併發學習筆記 2

2022-08-01 06:06:12 字數 2552 閱讀 7331

等待乙個時間或其他條件

在乙個執行緒等待完成任務時,會有很多選擇:

1. 它可以持續的檢查共享資料標誌(用於做保護工作的互斥量),直到另乙個執行緒完成工作時對這個標誌進行重設。缺點:資源浪費,開銷大

2. 在等待執行緒的檢查間隙,使用std::this_thread::sleep_for()進行週期性的間歇。 缺點:休眠時間抉擇困難

bool

flag;

std::mutex m;

void

wait_for_flag()

}

3. 使用c++標準庫提供的工具去等待事件的發生。通過另一線程觸發等待事件的機制是最基本的喚醒方式,這種機制就稱為「條件變數」。

c++標準庫對條件變數有兩套實現:std::condition_variablestd::condition_variable_any。這兩個實現都包含在標頭檔案的宣告中。兩者都需要與乙個互斥量一起才能工作(互斥量是為了同步)

std::condition_variable:只能與std::mutex一起工作,開銷少

std::condition_variable_any:可以和任何滿足最低標準的互斥量一起工作,開銷大

std::condition_variable 提供兩個重要的介面:notify_one()wait()。wait()可以讓執行緒陷入休眠狀態,notify_one()就是喚醒處於wait中的其中乙個條件變數(可能當時有很多條件變數都處於wait狀態)。

templatewait(std::unique_lock

& lk, predicate pred)

wait()會去檢查這些條件(通過呼叫所提供的函式),當條件滿足(呼叫所提供的函式返回true)時返回。如果條件不滿足(呼叫所提供的函式返回false),wait()函式將解鎖互斥量,並且將這個執行緒置於阻塞或等待狀態。另外乙個執行緒呼叫notify_one()通知條件變數時,執行緒從睡眠狀態中甦醒,重新獲取互斥鎖,並且再次檢查條件是否滿足。

std::condition_variable::wait的乙個最小化實現:

templatevoid minimal_wait(std::unique_lock&lk,predicate pred)

}

考慮乙個生產者消費者模型:乙個執行緒往佇列中放入資料,乙個執行緒往佇列中取資料,取資料前需要判斷一下佇列中確實有資料,由於這個佇列是執行緒間共享的,所以,需要使用互斥鎖進行保護,乙個執行緒在往佇列新增資料的時候,另乙個執行緒不能取,反之亦然。用互斥鎖實現如下:

#include #include 

#include

#include

std::deque

q;std::mutex mu;

void

function_1()

}void

function_2()

else

}}int

main()

問題在於,如果生產者的速度比較慢,**中每隔1s才會有一次資料生產,這時消費者都要去獲取鎖-->判斷佇列裡是否有資料-->釋放鎖,這個過程就是資源的浪費,無用功使得cpu佔用率很高。

使用std::this_thread::sleep_for()來對**進行改造:

void

function_2()

else

}}

這樣可以減低cpu佔用率,但問題在於在實際操作中如何選擇休眠時間,太長或者太短都不好。

最後可以使用條件變數來對這個**進行改造:

#include #include 

#include

#include

#include

std::deque

q;std::mutex mu;

std::condition_variable cond;

void

function_1()

}void

function_2() ); //

unlock mu and wait to be notified

data =q.back();

q.pop_back();

locker.unlock();

std::cout

<< "

t2 got a value from t1:

"<< data <}

}int

main()

需要注意的幾點:

在配合條件變數使用鎖時,使用std::unique_lock比std::lock_guard合適,因為在wait內部有對鎖的unlock和lock操作

使用細粒度鎖,盡量減小鎖的範圍,在notify_one()的時候,不需要處於互斥鎖的保護範圍內,所以在喚醒條件變數之前可以將鎖unlock()

多執行緒(併發)學習筆記

1,無論以哪種方式啟動乙個執行緒,要給執行緒乙個名字,對排錯 監控有幫助。2,要對執行緒interrupt做處理。3,futrure 是任務的提交者和執行者之間的通訊手段,get 會阻塞 executorservice executor executors.newsinglethreadexecut...

C 多執行緒學習2

include stdafx.h include beginthread.h ifdef debug define new debug new undef this file static char this file file endif include stdafx.h include wind...

C C 筆記 2 多執行緒 併發 互斥鎖

1.1 執行緒的管理 乙個程序中至少存在乙個執行緒,這個執行緒被稱為主線程,我們可以在任意執行緒中建立執行緒類的例項。每個執行緒都需要乙個入口函式,當入口函式返回時,執行緒就會退出,主線程的入口函式為main 1.1.1 執行緒的啟動 執行緒的建立十分簡單,我們只需建立乙個執行緒類的例項,並為它傳入...