C11執行緒管理 條件變數

2022-05-07 00:48:12 字數 3471 閱讀 4749

c11提供另外一種用於等待的同步機制,它可以阻塞乙個或者多個執行緒,直到收到另外乙個執行緒發出的通知或者超時,才會喚醒當前阻塞的執行緒。條件變數要和互斥量配合起來使用。

condition_variable,配合std::unique_lock進行wait操作。

condition_variable_any,和任意帶有lock、unlock語意 的mutex搭配使用,比較靈活,但是效率比condition_variable低。

條件變數的使用過程如下:

a.擁有條件變數的執行緒獲取互斥量。

b.迴圈檢查某個條件,如果條件不滿足,則阻塞執行緒直到滿足;如果條件滿足,則向下執行。

c.某個執行緒滿足條件並執行完成之後,呼叫notify_one或者notify_all來喚醒乙個或者多個執行緒。

可以用條件變數來實現乙個同步佇列,同步佇列作為乙個執行緒安全的資料共享區,經常用於執行緒之間的讀取,比如半同步半非同步執行緒池的同步佇列。

#include #include 

#include

#include

#include

#include

template

class

syncqueue

void put(const t &t)

m_queue.push_back(t);

m_notempty.notify_one();

}void take(const t &t)

t =m_queue.front();

m_queue.pop_front(t);

m_notfull.notify_one();

}bool

empty()

bool

full()

size_t size()

private

:

bool isfull() const

bool isempty() const

private

: std::list

m_queue;              //

緩衝區 std::mutex m_mutex;              //

互斥量 std::condition_variable_any m_notempty; //

不為空的條件變數

std::condition_variable_any m_notfull; //

沒有滿的條件變數

int m_maxsize;            //

同步佇列最大容量

};

這個佇列中,沒有滿的情況下可以插入資料,如果滿了,則會呼叫m_notfull阻塞執行緒等待,等待消費執行緒取出資料之後發出乙個未滿的通知,然後前面阻塞的執行緒會被喚醒繼續往下執行;如果隊列為空,不能取出資料,呼叫m_notempty來阻塞當前執行緒,等待插入資料的執行緒插入資料發出不為空的通知,喚醒被阻塞的執行緒,往下執行讀出資料。

條件變數的wait方法還有個過載方法,可以接受乙個條件。

std::lock_guardlocker(m_mutex);

while

(isfull())

可以寫為這樣:

std::lock_guardlocker(m_mutex);

m_notfull.wait(locker, [

this]);

兩種寫法都一樣,後者**更加簡潔,條件變數先檢查判斷式是否滿足條件,如果滿足,重新獲取mutex,結束wait,繼續往下執行;如果不滿足條件,則釋放mutex,將執行緒置為waiting狀態,繼續等待。

需要注意的是,wait函式會釋放掉mutex,而lock_guard還擁有mutex,他只在出了作用域之後才會釋放掉mutex,所以這時並不會釋放,但是執行wait會提前釋放,而在wait提前釋放掉鎖之後,會處於等待狀態,在notify_one/all喚醒之後,會先獲取mutex,相當於之前的mutex又獲取到了,所以在出作用域的時候,lock_guard釋放鎖不會產生問題。

在這種情況下,如果用unique_lock語意更準確,因為unique_lock不像lock_guard一樣只能在析構的時候才能釋放鎖,它可以隨時釋放鎖,在wait的時候讓uniq_lock釋放鎖,語意更加準確。

上述例子中,可以用unique_lock來替換掉lock_guard,condition_variable來替換掉condition_variable_any,會使**更加清晰,效率也更高。

除了wait還可以使用超時等待函式std::condition_variable::wait_for和std::condition_variable::wait_until。

與 std::condition_variable::wait() 類似,不過 wait_for 可以指定乙個時間段,在當前執行緒收到通知或者指定的時間 rel_time 超時之前,該執行緒都會處於阻塞狀態。而一旦超時或者收到了其他執行緒的通知,wait_for 返回,剩下的處理步驟和 wait() 類似。

與 std::condition_variable::wait_for 類似,但是 wait_until 可以指定乙個時間點,在當前執行緒收到通知或者指定的時間點 abs_time 超時之前,該執行緒都會處於阻塞狀態。而一旦超時或者收到了其他執行緒的通知,wait_until 返回,剩下的處理步驟和 wait_for() 類似。

//

condition_variable::wait_for example

#include //

std::cout

#include //

std::thread

#include //

std::chrono::seconds

#include //

std::mutex, std::unique_lock

#include //

std::condition_variable, std::cv_status

std::condition_variable cv;

intvalue;

void

read_value()

intmain ()

std::cout

<< "

you entered:

"<< value << '\n'

; //等待th執行緒執行完

th.join();

return0;

}

如果用wait_until,只需要將條件改為時間點即可:

while (cv.wait_for(lck,std::chrono::seconds(1))==std::cv_status::timeout)

while (cv.wait_until(lck, std::chrono::system_clock::now() +std::chrono::seconds(1)) == std::cv_status::timeout)

C 11多執行緒學習 條件變數

c 11中的std condition variable 首先,舉個例子 在應用程式中有4個程序thread1,thread2,thread3和thread4,有乙個int型別的全域性變數icount。icount初始化為0,thread1和thread2的功能是對icount的加1,thread3...

3執行緒同步 C 11中的條件變數

在c11標頭檔案中包含了如下內容 cv status 條件等待結果的列舉。condition variable 條件變數的主要類,用於實現執行緒同步。condition variable any 是對condition variable的擴充套件,condition variable只能等待uniq...

C 11 多執行緒同步 互斥鎖 條件變數

在多執行緒程式中,執行緒同步 多個執行緒訪問乙個資源保證順序 是乙個非常重要的問題,linux下常見的執行緒同步的方法有下面幾種 這篇部落格只介紹互斥量和條件變數的使用。通常情況下,互斥鎖和條件變數是配合使用的,互斥鎖用於短期鎖定,主要保證執行緒對臨界區的進入 條件變數用於執行緒長期等待,在wait...