linux條件變數使用和與訊號量的區別
近來在專案中用到條件變數和訊號量做同步時,這一塊一直都有了解,但也一直沒有總結,這次總結一下,給大家提供點參考,也給自己留點紀念。
首先,關於訊號量和條件變數的概念可以自行檢視APUE,我這直接把APUE中的程式碼拿過來對比;
條件變數的使用:
#include <pthread.h> struct msg { struct msg *m_next; /* ... more stuff here ... */ }; struct msg *workq; pthread_cond_t qready = PTHREAD_COND_INITIALIZER; pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER; void process_msg(void) { struct msg *mp; for (;;) { pthread_mutex_lock(&qlock); while (workq == NULL) pthread_cond_wait(&qready, &qlock); mp = workq; workq = mp->m_next; pthread_mutex_unlock(&qlock); /* now process the message mp */ } } void enqueue_msg(struct msg *mp) { pthread_mutex_lock(&qlock); mp->m_next = workq; workq = mp; pthread_mutex_unlock(&qlock); pthread_cond_signal(&qready); }
其中最後在呼叫也可以按照下面格式呼叫,兩種各有優劣,具體可以參考:https://www.cnblogs.com/charlesblc/p/6143397.html
pthread_mutex_lock(&qlock); mp->m_next = workq; workq = mp;
pthread_cond_signal
pthread_mutex_unlock
條件變數和訊號量的區別:
(1)使用條件變數可以一次喚醒所有等待者,而這個訊號量沒有的功能,感覺是最大區別。
(2)訊號量是有一個值(狀態的),而條件變數是沒有的,沒有地方記錄喚醒(傳送訊號)過多少次,也沒有地方記錄喚醒執行緒(wait返回)過多少次。從實現上來說一個訊號量可以是用mutex + counter + condition variable實現的。因為訊號量有一個狀態,如果想精準的同步,那麼訊號量可能會有特殊的地方。訊號量可以解決條件變數中存在的喚醒丟失問題。
(3)在Posix.1基本原理一文聲稱,有了互斥鎖和條件變數還提供訊號量的原因是:“本標準提供訊號量的而主要目的是提供一種程序間同步的方式;這些程序可能共享也可能不共享記憶體區。互斥鎖和條件變數是作為執行緒間的同步機制說明的;這些執行緒總是共享(某個)記憶體區。這兩者都是已廣泛使用了多年的同步方式。每組原語都特別適合於特定的問題”。儘管訊號量的意圖在於程序間同步,互斥鎖和條件變數的意圖在於執行緒間同步,但是訊號量也可用於執行緒間,互斥鎖和條件變數也可用於程序間。應當根據實際的情況進行決定。訊號量最有用的場景是用以指明可用資源的數量。
經典的一句話:
互斥量是訊號量的一種特例,互斥量的本質是一把鎖。A mutex is basically a lock that we set (lock) before accessing a shared resource and release (unlock) when we're