近來在項目中用到條件變量和信號量做同步時,這一塊一直都有了解,但也一直沒有總結,這次總結一下,給大家提供點參考,也給自己留點紀念。
首先,關於信號量和條件變量的概念可以自行查看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
void enqueue_msg(struct msg *mp) { pthread_mutex_lock(&qlock); mp->m_next = workq; workq = mp; pthread_cond_signal(&qready); pthread_mutex_unlock(&qlock); }
二,工作中的使用:
typedef struct _STAT { int b_stop; MDL_COND_T cond; }STAT; STAT g_enc_stat; pthread_mutex_t mutex; pthread_cond_t cond;//可以放在結構體里面 pthread_cond_init(&cond); pthread_mutex_init(&mutex); int dsp_thread_start(unsigned int trmn) { pthread_mutex_lock(&mutex); ... if(1 == g_enc_stat.b_stop) { g_enc_stat.b_stop = 0; pthread_cond_signal(&cond); } pthread_mutex_unlock(&mutex); return OK; } /************************************** * @fn * @brief * @param * @return * @other ***************************************/ int dsp_thread_stop(unsigned int trmn) { pthread_mutex_lock(&mutex); ... g_enc_stat.b_stop = 1; pthread_mutex_unlock(&mutex); return OK; } void dsp_thread(void) {
for(;;)
{
pthread_mutex_lock(&mutex);//不僅用於同步,還可以用於stop時互斥(線程執行時原子操作) if(g_enc_stat.b_stop) { pthread_cond_wait(&cond,&mutex); pthread_mutex_unlock(&mutex);//這個地方也可以不用,參考上述代碼,直接執行下面 continue; } . . . pthread_mutex_unlock(&mutex);
} }
三,條件變量和信號量的區別:
(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 done