1. 程式人生 > >linux條件變數使用和與訊號量的區別

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