免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項超值服

開通VIP
【轉(zhuǎn)】POSIX線程庫條件變量的使用——Pthreads線程庫實(shí)例筆記4 - BlueClue's Blog - 博客園

條件變量(Condition Variables)

條件變量是什么?

  • 條件變量為我們提供了另一種線程間同步的方法,然而,互斥量是通過控制線程訪問數(shù)據(jù)來實(shí)現(xiàn)同步,條件變量允許線程同步是基于實(shí)際數(shù)據(jù)的值。
  • 如果沒有條件變量,程序員需要讓線程不斷地輪詢,以檢查是否滿足條件。由于線程處在一個不間斷的忙碌狀態(tài),所以這是相當(dāng)耗資源的。條件變量就是這 么一個不需要輪詢就可以解決這個問題的方法。
  • 條件變量總是跟互斥鎖(mutex lock)一起使用。
  • 下面是使用條件變量的比較典型的過程:
主線程
  • 聲明并初始化需要同步的全局?jǐn)?shù)據(jù)或變量(例如”count“)
  • 聲明并初始化一個條件變量對象
  • 聲明并初始化一個與條件變量關(guān)聯(lián)的互斥量
  • 創(chuàng)建線程A和B并開始運(yùn)行
線程A
  • 線程運(yùn)轉(zhuǎn)至某一個條件被觸發(fā)(例如,”count“必須達(dá)到某個值)
  • 鎖定相關(guān)聯(lián)的互斥量并檢查全局變量的值
  • 調(diào)用pthread_con_wait()阻塞線程等待線程B的信號。請注意, 調(diào)用pthread_con_wait()以自動的原子方式(atomically)解鎖相關(guān)聯(lián)的互斥量,以便于可以被線程B使用。
  • 當(dāng)收到信號時,喚醒線程。互斥量被以自動的原子方式被鎖定。
  • 明確的解鎖互斥量。
  • 繼續(xù)
Thread B
  • 線程運(yùn)轉(zhuǎn)
  • 鎖定相關(guān)聯(lián)的互斥量
  • 更改線程A正在等待的全局變量的值
  • 檢查線程A等待的變量值,如果滿足條件,發(fā)信號給線程A
  • 解鎖互斥量
  • 繼續(xù)
主線程
    Join / Continue

 

 

創(chuàng)建和銷毀條件變量

函數(shù):

pthread_cond_init (condition,attr)

pthread_cond_destroy (condition)

pthread_condattr_init (attr)

pthread_condattr_destroy (attr)

用法:

  • 條件變量必須聲明為pthread_cond_t類型,并且在使用前必須要初始化。初始化,有兩種方法:
  1. 靜態(tài)初始化,像這樣聲明:pthread_con_t myconvar = PTHREAD_CON_INITIALIZER;
  2. 動態(tài)初始化,使用pthread_cond_init()函數(shù)。用創(chuàng)建條件變量的ID作為件參數(shù)傳給線程,這種方法允許設(shè)置條件變量對象屬性 attr。
  • 可設(shè)置的attr對象經(jīng)常用來設(shè)置條件變量的屬性,條件變量只有一種屬性:process-thread,它的作用是允許條件變量被其它進(jìn)程的線 程看到。如果使用屬性對象,必須是pthread_condattr_t類型(也可以賦值為NULL,作為默認(rèn)值)。

        注意,不是所有的實(shí)現(xiàn)都用得著process-shared屬性。

  • pthread_condattr_init()和pthread_condattr_destroy()函數(shù)是用來創(chuàng)建和銷毀條件變量屬性對象 的。
  • 當(dāng)不再需要某條件變量時,可用pthread_cond_destroy()銷毀。

 

條件變量的等待和信號發(fā)送

函數(shù):

pthread_cond_wait (condition,mutex)

pthread_cond_signal (condition)

pthread_cond_broadcast (condition)

使用:

  • pthread_cond_wait()阻塞調(diào)用線程,直到指定的條件變量收到信號。當(dāng)互斥量被鎖定時,應(yīng)該調(diào)用這個函數(shù),并且在等待時自動釋放 這個互斥量,在接收到信號后線程被喚醒,線程的互斥量會被自動鎖定,程序員在線程中應(yīng)當(dāng)在此函數(shù)后解鎖互斥量。
  • pthread_cond_signal()函數(shù)常用來發(fā)信號給(或喚醒)正在等待條件變量的另一個線程,在互斥量被鎖定后應(yīng)該調(diào)用這個函數(shù),并 且為了pthread_cond_wait()函數(shù)的完成必須要解鎖互斥量。
  • 如果多個線程處于阻塞等待狀態(tài),那么必須要使用pthreads_cond_broadcast()函數(shù),而不是 pthread_cond_signal()。
  • 在調(diào)用pthread_cond_wait()函數(shù)之前調(diào)用pthread_cond_signal()函數(shù)是個邏輯上的錯誤,所以,在使用這些 函數(shù)時,正確的鎖定和解鎖與條件變量相關(guān)的互斥量是非常必要的,例如:
  1. 在調(diào)用pthread_cond_wait()之前鎖定互斥量失敗,可致使其無法阻塞;
  2. 在調(diào)用pthread_cond_signal()之后解鎖互斥量失敗,則致使與之對應(yīng)的pthread_cond_wait()函數(shù)無法完成, 并仍保持阻塞狀態(tài)。

 

實(shí)例分析

看到下面的一汪代碼不要撓頭,99行而已,之后會抽絲剝繭,目的是對條件變量的運(yùn)行機(jī)制了解個大概:

 

實(shí)例代碼
/******************************************************************************
* 描述:
* 應(yīng)用Pthreads條件變量的實(shí)例代碼,主線程創(chuàng)建三個線程,其中兩個為“count”變量做
* 加法運(yùn)算,第三個線程監(jiān)視“count”的值。當(dāng)“count”達(dá)到一個限定值,等待線程準(zhǔn)備接收來
* 自于兩個加法線程中一個的信號,等待 線程喚醒后更改“count”的值。程序繼續(xù)運(yùn)行直到加法
* 線程達(dá)到TCOUNT的值。最后,主程序打印出count的值。
*****************************************************************************
*/
#include
<pthread.h>
#include
<stdio.h>
#include
<stdlib.h>

#define NUM_THREADS 3
#define TCOUNT 5 //單線程輪詢次數(shù)
#define COUNT_LIMIT 7 //發(fā)送信號的次數(shù)
int count = 0; //全局的累加量

pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv;

void *inc_count(void *t) {
int i;
long my_id = (long) t;

for (i = 0; i < TCOUNT; i++) {
pthread_mutex_lock(
&count_mutex);
count
++;
/*
* 檢查count的值,如果條件滿足就發(fā)信號給等待線程
* 注意,此處是用信號量鎖定的。
*
*/
if (count < COUNT_LIMIT) {
printf(
"inc_count(): thread %ld, count = %d Threshold reached. ",
my_id, count);
pthread_cond_signal(
&count_threshold_cv);
printf(
"Just sent signal.\n");
}
printf(
"inc_count(): thread %ld, count = %d, unlocking mutex\n", my_id,
count);
pthread_mutex_unlock(
&count_mutex);

/*為線程輪詢互斥鎖增加延時*/
sleep(
1);
}
pthread_exit(NULL);
}

void *watch_count(void *t) {
long my_id = (long) t;
printf(
"Starting watch_count(): thread %ld\n", my_id);

/*鎖定互斥量并等待信號,注意,pthread_cond_wait函數(shù)在等待時將自動以自動原子方式
* 解鎖互斥量。還有,請注意,如果等待線程運(yùn)行到等待函數(shù)之前已經(jīng)滿足COUNT_LIMIT的
* 條件判斷,輪詢會忽略掉等待函數(shù),
*
*/
while (count < COUNT_LIMIT) {
pthread_mutex_lock(
&count_mutex);
printf(
"watch_count(): thread %ld going into wait...\n", my_id);
pthread_cond_wait(
&count_threshold_cv, &count_mutex);
printf(
"watch_count(): thread %ld Condition signal received.\n", my_id);

printf(
"watch_count(): thread %ld count now = %d.\n", my_id, count);
pthread_mutex_unlock(
&count_mutex);
}
pthread_exit(NULL);
}

int main(int argc, char *argv[]) {
int i;
long t1 = 1, t2 = 2, t3 = 3;
pthread_t threads[
3];
pthread_attr_t attr;

/*初始化互斥量和條件變量對象*/
pthread_mutex_init(
&count_mutex, NULL);
pthread_cond_init(
&count_threshold_cv, NULL);

/*創(chuàng)建線程時設(shè)為可連接狀態(tài),便于移植*/
pthread_attr_init(
&attr);
pthread_attr_setdetachstate(
&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(
&threads[0], &attr, watch_count, (void *) t1);
pthread_create(
&threads[1], &attr, inc_count, (void *) t2);
pthread_create(
&threads[2], &attr, inc_count, (void *) t3);

/* 等待所有線程完成*/
for (i = 1; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
/*發(fā)送信號給監(jiān)聽線程*/
pthread_cond_signal(
&count_threshold_cv);
pthread_join(threads[
0],NULL);
printf(
"Main(): Waited on %d threads. Final value of count = %d. Done.\n",
NUM_THREADS, count);

/*清除并退出 */
pthread_attr_destroy(
&attr);
pthread_mutex_destroy(
&count_mutex);
pthread_cond_destroy(
&count_threshold_cv);
pthread_exit(NULL);
}

 

  • 主線程創(chuàng)建了3個子線程,一個線程用來監(jiān)聽信號(threads[0],調(diào)用watch_count()函數(shù)),兩個線程用來發(fā)送信號 (threads[1]、threads[2],調(diào)用inc_count()函數(shù));
  • 兩個發(fā)送信號線程,主要負(fù)責(zé)兩件事:
  1. 兩個線程利用互斥量為count做加法運(yùn)算,兩個線程一起做了(2*TCOUNT=)10次運(yùn)算;
  2. count值小于COUNT_LIMIT時,發(fā)送信號給監(jiān)聽線程;
  • 監(jiān)聽線程作用只有一個,就是如果count值小于COUNT_LIMIT則等待線程;
  • 整體來講,就是兩個發(fā)送信號的線程讓count做迭加運(yùn)算,并在迭加到一定值之前給監(jiān)聽線程發(fā)送信號,監(jiān)聽線程收到打印信息
  • 兩個地方需要注意一下:
    1. pthread_cond_wait()有解鎖和鎖定互斥量的操作,它所進(jìn)行的操作大體有三步:解鎖—阻塞監(jiān)聽—鎖定,所以在監(jiān)聽線程的循環(huán)體里 面有兩次“鎖定-解鎖”的操作;
    2. 主函數(shù)main最后的pthread_cond_signal()這句必不可少,因?yàn)楸O(jiān)聽線程運(yùn)轉(zhuǎn)沒有延時,在count的值達(dá)到 COUNT_LIMIT-1時,已經(jīng)處于waiting狀態(tài)。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Linux下的多線程編程
Linux系統(tǒng)下的多線程編程入門-開發(fā)頻道-多線程-天極網(wǎng)
pthread高級部分整理
線程通信
pthread條件變量函數(shù)的使用
POSIX 多線程程序設(shè)計
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服