日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

linux 条件变量函数,Linux线程同步之条件变量

發(fā)布時(shí)間:2024/9/19 linux 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 条件变量函数,Linux线程同步之条件变量 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

條件變量變量也是出自POSIX線程標(biāo)準(zhǔn),另一種線程同步機(jī)制,。主要用來等待某個(gè)條件的發(fā)生。可以用來同步同一進(jìn)程中的各個(gè)線程。當(dāng)然如果一個(gè)條件變量存放在多個(gè)進(jìn)程共享的某個(gè)內(nèi)存區(qū)中,那么還可以通過條件變量來進(jìn)行進(jìn)程間的同步。

每個(gè)條件變量總是和一個(gè)互斥量相關(guān)聯(lián),條件本身是由互斥量保護(hù)的,線程在改變條件狀態(tài)之間必須要鎖住互斥量。條件變量相對(duì)于互斥量最大的優(yōu)點(diǎn)在于允許線程以無競(jìng)爭(zhēng)的方式等待條件的發(fā)生。當(dāng)一個(gè)線程獲得互斥鎖后,發(fā)現(xiàn)自己需要等待某個(gè)條件變?yōu)檎?#xff0c;如果是這樣,該線程就可以等待在某個(gè)條件上,這樣就不需要通過輪詢的方式來判斷添加,大大節(jié)省了CPU時(shí)間。

在互斥量一文中說過:互斥量是用于上鎖,而不是用于等待;現(xiàn)在這句話可以加強(qiáng)為:互斥量是用于上鎖,條件變量用于等待;

條件變量聲明為pthread_cond_t數(shù)據(jù)類型,在中有具體的定義。

1、條件變量初始化和銷毀

/* Initialize condition variable */

int pthread_cond_init (pthread_cond_t *__restrict __cond,

__const pthread_condattr_t *__restrict __cond_attr) ;

/* Destroy condition variable */

int pthread_cond_destroy (pthread_cond_t *__cond);

上面兩個(gè)函數(shù)分別由于條件變量的初始化和銷毀。

和互斥量的初始化一樣,如果條件變量是靜態(tài)分配的,可以通過常量進(jìn)行初始化,如下:

pthread_cond_t mlock = PTHREAD_COND_INITIALIZER;

也可以通過pthread_cond_init()進(jìn)行初始化,對(duì)于動(dòng)態(tài)分配的條件變量由于不能直接賦值進(jìn)行初始化,就只能采用這種方式進(jìn)行初始化。那么當(dāng)不在需要使用條件變量時(shí),需要調(diào)用pthread_cond_destroy()銷毀該條件所占用的資源。

2、條件變量的屬性設(shè)置

/* 初始化條件變量屬性對(duì)象 */

int pthread_condattr_init (pthread_condattr_t *__attr);

/* 銷毀條件變量屬性對(duì)象 */

int pthread_condattr_destroy (pthread_condattr_t *__attr);

/* 獲取條件變量屬性對(duì)象在進(jìn)程間共享與否的標(biāo)識(shí) */

int pthread_condattr_getpshared (__const pthread_condattr_t * __restrict __attr,

int *__restrict __pshared);

/* 設(shè)置條件變量屬性對(duì)象,標(biāo)識(shí)在進(jìn)程間共享與否 */

int pthread_condattr_setpshared (pthread_condattr_t *__attr, int __pshared) ;

這個(gè)屬性的設(shè)置和互斥量屬性設(shè)置是一樣的,具體使用可以參考互斥量的用法:互斥量的屬性設(shè)置。

3、條件變量的使用

/* 等待條件變?yōu)檎?*/

int pthread_cond_wait (pthread_cond_t *__restrict __cond,

pthread_mutex_t *__restrict __mutex);

/* 限時(shí)等待條件為真 */

int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,

pthread_mutex_t *__restrict __mutex,

__const struct timespec *__restrict __abstime);

/* 喚醒一個(gè)等待條件的線程. */

int pthread_cond_signal (pthread_cond_t *__cond);

/* 喚醒等待該條件的所有線程 */

int pthread_cond_broadcast (pthread_cond_t *__cond);

(1)pthread_cond_wait()函數(shù)用于等待條件被觸發(fā)。該函數(shù)傳入兩個(gè)參數(shù),一個(gè)條件變量一個(gè)互斥量,函數(shù)將條件變量和互斥量進(jìn)行關(guān)聯(lián),互斥量對(duì)該條件進(jìn)行保護(hù),傳入的互斥量必須是已經(jīng)鎖住的。調(diào)用pthread_cond_wait()函數(shù)后,會(huì)原子的執(zhí)行以下兩個(gè)動(dòng)作:

1)將調(diào)用線程放到等待條件的線程列表上,即進(jìn)入睡眠;

2)對(duì)互斥量進(jìn)行解鎖;

由于這兩個(gè)操作時(shí)原子操作,這樣就關(guān)閉了條件檢查和線程進(jìn)入睡眠等待條件改變這兩個(gè)操作之間的時(shí)間通道,這樣就不會(huì)錯(cuò)過任何條件的變化。

當(dāng)pthread_cond_wait()返回后,互斥量會(huì)再次被鎖住。

(2)pthread_cond_timedwait()函數(shù)和pthread_cond_wait()的工作方式相似,只是多了一個(gè)等待時(shí)間。等待時(shí)間的結(jié)構(gòu)為struct

timespec,

/* 等待條件變?yōu)檎?*/

int pthread_cond_wait (pthread_cond_t *__restrict __cond,

pthread_mutex_t *__restrict __mutex);

/* 限時(shí)等待條件為真 */

int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,

pthread_mutex_t *__restrict __mutex,

__const struct timespec *__restrict __abstime);

/* 喚醒一個(gè)等待條件的線程. */

int pthread_cond_signal (pthread_cond_t *__cond);

/* 喚醒等待該條件的所有線程 */

int pthread_cond_broadcast (pthread_cond_t *__cond);

函數(shù)要求傳入的時(shí)間值是一個(gè)絕對(duì)值,不是相對(duì)值,例如,想要等待3分鐘,必須先獲得當(dāng)前時(shí)間,然后加上3分鐘。

要想獲得當(dāng)前系統(tǒng)時(shí)間的timespec值,沒有直接可調(diào)用的函數(shù),需要通過調(diào)用gettimeofday函數(shù)獲取timeval結(jié)構(gòu),然后轉(zhuǎn)換成timespec結(jié)構(gòu),轉(zhuǎn)換公式就是:

/* 等待條件變?yōu)檎?*/

int pthread_cond_wait (pthread_cond_t *__restrict __cond,

pthread_mutex_t *__restrict __mutex);

/* 限時(shí)等待條件為真 */

int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,

pthread_mutex_t *__restrict __mutex,

__const struct timespec *__restrict __abstime);

/* 喚醒一個(gè)等待條件的線程. */

int pthread_cond_signal (pthread_cond_t *__cond);

/* 喚醒等待該條件的所有線程 */

int pthread_cond_broadcast (pthread_cond_t *__cond);

所以要等待3分鐘,timespec時(shí)間結(jié)構(gòu)的獲得應(yīng)該如下所示:

struct timeval now;

struct timespec until;

gettimeofday(&now);//獲得系統(tǒng)當(dāng)前時(shí)間

//把時(shí)間從timeval結(jié)構(gòu)轉(zhuǎn)換成timespec結(jié)構(gòu)

until.tv_sec = now.tv_sec;

until.tv_nsec = now.tv_usec * 1000;

//增加min

until.tv_sec += 3 * 60;

如果時(shí)間到后,條件還沒有發(fā)生,那么會(huì)返回ETIMEDOUT錯(cuò)誤。

從pthread_cond_wait()和pthread_cond_timewait()成功返回時(shí),線程需要重新計(jì)算條件,因?yàn)槠渌€程可能在運(yùn)行過程中已經(jīng)改變條件。

(3)pthread_cond_signal() & pthread_cond_broadcast()

這兩個(gè)函數(shù)都是用于向等待條件的線程發(fā)送喚醒信號(hào),pthread_cond_signal()函數(shù)只會(huì)喚醒等待該條件的某個(gè)線程,pthread_cond_broadcast()會(huì)廣播條件狀態(tài)的改變,以喚醒等待該條件的所有線程。例如多個(gè)線程只讀共享資源,這是可以將它們都喚醒。

這里要注意的是:一定要在改變條件狀態(tài)后,再給線程發(fā)送信號(hào)。

考慮條件變量信號(hào)單播發(fā)送和廣播發(fā)送的一種候選方式是堅(jiān)持使用廣播發(fā)送。只有在等待者代碼編寫確切,只有一個(gè)等待者需要喚醒,且喚醒哪個(gè)線程無所謂,那么此時(shí)為這種情況使用單播,所以其他情況下都必須使用廣播發(fā)送。

下面是一個(gè)測(cè)試代碼,模擬同步問題中經(jīng)典的生產(chǎn)者消費(fèi)者問題。

#include

#include

#include

#include

#include

using namespace std;

//把共享數(shù)據(jù)和它們的同步變量集合到一個(gè)結(jié)構(gòu)中,這往往是一個(gè)較好的編程技巧。

struct{

pthread_mutex_t mutex;

pthread_cond_t cond;

queue product;

}sharedData = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};

void * produce(void *ptr)

{

for (int i = 0; i < 10; ++i)

{

pthread_mutex_lock(&sharedData.mutex);

sharedData.product.push(i);

pthread_mutex_unlock(&sharedData.mutex);

if (sharedData.product.size() == 1)

pthread_cond_signal(&sharedData.cond);

//sleep(1);

}

}

void * consume(void *ptr)

{

for (int i = 0; i < 10;)

{

pthread_mutex_lock(&sharedData.mutex);

while(sharedData.product.empty())

pthread_cond_wait(&sharedData.cond, &sharedData.mutex);

++i;

cout<

sharedData.product.pop();

pthread_mutex_unlock(&sharedData.mutex);

//sleep(1);

}

}

int main()

{

pthread_t tid1, tid2;

pthread_create(&tid1, NULL, consume, NULL);

pthread_create(&tid2, NULL, produce, NULL);

void *retVal;

pthread_join(tid1, &retVal);

pthread_join(tid2, &retVal);

return 0;

}

程序的運(yùn)行結(jié)果如下所示:

consume:0

consume:1

consume:2

consume:3

consume:4

consume:5

consume:6

consume:7

consume:8

consume:9

與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的linux 条件变量函数,Linux线程同步之条件变量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。