Linux多執行緒 條件變數

2021-09-23 14:15:21 字數 4173 閱讀 1811

在多執行緒程式設計中僅使用互斥鎖來完成互斥是不夠用的,如以下情形:

假設有兩個執行緒 t1 和 t2, 需要這個兩個執行緒迴圈對乙個共享變數 sum 進行自增操作,那麼 t1 和 t2 只需要使用互斥量即可保證操作正確完成,執行緒執行**如所示:

pthread_mutex_t sumlock=pthread_mutex-initializer;

void *t1t2(void)

如果這時需要增加另乙個執行緒 t3,需要 t3 在 count 大於 100 時將 count 值重新置 0 值,那麼可以 t3 可以實現如下:

void *t3(void)

else

}

以上**存在以下問題:1) sum 在大多數情況下不會到達 100, 那麼對 t3 的**來說,大多數情況下, 走的是 else分支, 只是 lock 和 unlock,然後sleep()。 這浪費了 cpu 處理時間。2) 為了節省 cpu 處理時間, t3 會在探測到 sum 沒到達 100 的時候 usleep()一段時間。這樣卻又帶來另外乙個問題, 亦即 t3 響應速度下降。 可能在 sum 到達 200 的時候, t3 才會醒過來。這樣時間與效率出現了矛盾,而條件變數就是解決這個問題的好方法。pthreads用pthread_cond_t型別的變數來表示條件變數,要先進行初始化

(1)靜態初始化:對於靜態分配的變數可以簡單地將 pthread_cond_initializer 賦值給變數來初始化預設行為的條件變數。

pthread_cond_t cond=pthread_cond_initializer
(2)動態初始化:對動態分配或者不使用預設屬性的條件變數來說可以使用 pthread _cond_init()來初始化。函式原型如下:

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
引數 cond 是乙個指向需要初始化 pthread_cond_t 變數的指標,引數 attr 傳遞 null 值時, pthread_cond_init()將 cond 初始化為預設屬性的條件變數。函式成功將返回 0;否則返回乙個非 0 的錯誤碼。以下為**示例:

pthread_cond_t cond;

int err;

if(err=pthread_cond_init(&cond,null))

fprintf(stderr,"failed to initialize cond:%s\n",strerror(err));

函式 pthread_cond_destroy()用來銷毀它引數所指出的條件變數,函式原型如下:

int pthread_cond_destroy(pthread_cond_t *cond);
函式成功呼叫返回 0,否則返回乙個非 0 的錯誤碼。以下為**示例:

pthread_cond_t cond;

int err;

if(err=pthread_cond_destroy(&cond));

fprintf(stderr,"failed to destroy cond:%s\n",stderror(err));

條件變數是與條件測試一起使用的,通常執行緒會對乙個條件進行測試,如果條件不滿足就會呼叫條件等待函式來等待條件滿足。條件等待函式有 pthread_cond_wait()pthread_cond_timedwait()和兩個,函式原型如下:

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);

int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,

const struct timespec *restrict abstime);

pthread_cond_wait()函式在條件不滿足時將一直等待, 而 pthread_cond_timedwait()將只

等待一段時間。

引數 cond 是乙個指向條件變數的指標,引數 mutex 是乙個指向互斥量的指標,執行緒在呼叫前應該擁有這個互斥量,當執行緒要加入條件變數的等待佇列時,等待操作會使執行緒釋放這個互斥量。 pthread_timedwait()的第三個引數 abstime 是乙個指向返回時間的指標,如果條件變數通知訊號沒有在此等待時間之前出現,等待將超時退出, abstime 是個絕對時間,而不是時間間隔。以上函式成功呼叫返回 0,否則返回非 0 的錯誤碼,其中 pthread_cond_timedwait() 函式如果 abstime 指定的時間到期,錯誤碼為 etimeout。以下**使得執行緒進入等待,直到收到通知並且滿足 a 大於等於 b 的條件。

pthread_mutex_lock(&mutex);

while(a當另乙個執行緒修改了某引數可能使得條件變數所關聯的條件變成真時,它應該通知乙個或者多個等待在條件變數等待佇列中的執行緒。

條件通知函式有 pthread_cond_signal()和 pthread_cond_broadcast()函式,其中 pthread_cond_signal 函式可以喚醒乙個在條件變數等待佇列等待的執行緒,而 pthread_cond_broadcast函式可以喚醒所有在條件變數等待佇列等待的執行緒。函式原型如下:

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);

#include #include #include #include pthread_t tid[3];

int sum=0;

pthread_mutex_t sumlock=pthread_mutex_initializer; /*靜態初始化互斥量*/

pthread_cond_t cond_sum_ready=pthread_cond_initializer; /*靜態初始化條件變數*/

void *t1t2(void *arg)

return null;

}void *t3(void *arg)

sum=0;

printf("t3:clear sum value\n");

pthread_mutex_unlock(&sumlock);

return null;

}int main(int argc, char *ar**)

err=pthread_create(&tid[2],null,&t3,null); /*建立執行緒3*/

if(err!=0)

printf("can't create thread:%s\n",strerror(err));

for(i=0;i<3;i++)

return 0;

}

執行結果如圖所示。儘管程式會在 sum 累加到 100 時傳送條件通知,但正如圖中紅框出所示,當 sum 計算到 120 時 t3 才可能被呼叫,這是因為 signal 與 wait兩個呼叫之間存在可能的間隙

linux多執行緒 條件變數

include include include pthread mutex t mutex pthread mutex initializer 初始化互斥鎖 pthread cond t cond pthread cond initializer 初始化條件變數 void thread1 void ...

Linux多執行緒程式設計 條件變數

include int pthread cond init pthread cond t cv,const pthread condattr t cattr 返回值 函式成功返回0 任何其他返回值都表示錯誤初始化乙個條件變數。當引數cattr為空指標時,函式建立的是乙個預設的條件變數。否則條件變數的...

條件變數 多執行緒

最近看 unix環境高階程式設計 多執行緒同步,看到他舉例說條件變數pthread cond t怎麼用,愣是沒有看懂,只好在網上找了份 跑了跑,才弄明白 cpp view plain copy include include include pthread mutex t mutex pthread...