C C 互斥鎖和條件變數

2021-08-25 17:01:06 字數 4505 閱讀 3765

互斥鎖、條件變數和訊號量是實現執行緒間同步的三種方式。在多執行緒程式訪問臨界資源時,可以對各個執行緒進行訪問限制,每次只允許乙個執行緒訪問臨界資源。條件變數相當於是互斥鎖的一種補充,是執行緒中的東西,就是等待某一條件的發生,和訊號一樣。占有臨界資源的執行緒在執行完對於資源的操作後,會發出「訊號」,然後其它未占有資源的執行緒在感知到「訊號」後就會搶占資源。

需要的標頭檔案:pthread.h

1)定義並初始化互斥鎖

函式原型:pthread_mutex_t mutex;

int  pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mattr)

引數說明:mutex互斥鎖位址,mattr屬性通常預設nullptr,可以用於設定互斥鎖的特性。

互斥鎖屬性:

2)互斥鎖加鎖

函式原型:int pthread_mutex_lock(pthread_mutex_t *mutex);

函式說明:當 pthread_mutex_lock() 返回時,該互斥鎖已被鎖定。呼叫執行緒是該互斥鎖的屬主。如果該互斥鎖已被另乙個執行緒鎖定和擁有,則呼叫執行緒將阻塞,直到該互斥鎖變為可用為止。

返回值:成功返回0。其他任何返回值都表示出現了錯誤。錯誤返回值含義如下。

eagain:已超出了互斥鎖遞迴鎖定的最大次數,無法獲取該互斥鎖。

edeadlk:當前執行緒已經擁有互斥鎖。

3)互斥鎖解鎖

函式原型:int pthread_mutex_unlock(pthread_mutex_t *mutex);

函式說明:pthread_mutex_unlock() 釋放mutex引用的互斥鎖。互斥鎖的釋放方式取決於互斥鎖的型別屬性。對於 pthread_mutex_recursive 型別的互斥鎖,當計數達到零並且呼叫執行緒不再對該互斥鎖進行任何鎖定時,該互斥鎖將變為可用。

返回值:成功返回0,錯誤返回值含義如下。

eperm :當前執行緒不擁有互斥鎖。

4)使用非阻塞互斥鎖加鎖

函式原型:int pthread_mutex_trylock(pthread_mutex_t *mutex);

函式說明:pthread_mutex_trylock() 是 pthread_mutex_lock() 的非阻塞版本。如果 mutex 所引用的互斥物件當前被任何執行緒(包括當前執行緒)鎖定,則將立即返回該呼叫。否則,該互斥鎖將處於鎖定狀態,呼叫執行緒是其屬主。

返回值:成功返回0。錯誤返回值含義如下。

ebusy :mutex 所指向的互斥鎖已鎖定,無法獲取該互斥鎖。

eagain:超出了 mutex 的遞迴鎖定最大次數,無法獲取該互斥鎖。

5)銷毀互斥鎖

函式原型:int pthread_mutex_destroy(pthread_mutex_t *mutex);

返回值:pthread_mutex_destroy() 在成功完成之後會返回零。其他任何返回值都表示出現了錯誤。如果出現以下任一情況,該函式將失敗並返回對應的值。

einval:mutex 指定的值不會引用已初始化的互斥鎖物件。

需要的標頭檔案:pthread.h

1)定義並初始化條件變數

函式原型:pthread_cond_t cond = pthread_cond_initializer;

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);

引數說明:cond 條件變數位址,cond_attr屬性通常預設nullptr,可以用於設定互斥鎖的屬性。

2)等待條件變數

函式原型:int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

引數說明:cond 條件變數位址,mutex互斥鎖位址,表示鎖等待在條件變數上,abstime表示等待時限。

3)喚醒等待條件變數上的執行緒

函式原型:int pthread_cond_signal(pthread_cond_t *cond);               //喚醒等待該條件變數上的某個執行緒

int pthread_cond_broadcast(pthread_cond_t *cond);         //喚醒等待該條件變數上的所有執行緒

引數說明:cond條件變數位址。

4)銷毀條件變數

函式原型:int pthread_cond_destroy(pthread_cond_t *cond);

引數說明:cond條件變數位址

生產者和消費者模型:

消費者將count每次減去1,生產者將count每次加1,消費者會判斷count的大小,如果count==0那麼消費者執行緒要阻塞,但是它還會一直占有鎖,所以這樣就阻止了其它執行緒對count的操作,如果其它執行緒不能操作count,程式就沒有意義;因此我們要用到條件變數來解決這個問題。呼叫pthread_cond_wait(&cond, &mutex);讓互斥鎖mutex在這個cond條件上等待,執行緒呼叫pthread_cond_wait這個函式之後,核心會做下面這些事:

執行緒庫將上面三步做成了原子性操作,和linux核心繫結在一起。在生產者執行緒中當對count++之後(也就是生產了產品),會通過呼叫pthread_cond_signal(&cond)來向條件變數cond上傳送乙個訊號,表示條件滿足。如果條件滿足,那麼剛才因為呼叫pthread_cond_wait而等待的消費者執行緒會醒來(重新獲取鎖,並再次判斷條件是否滿足),如果count>0,就在臨界區進行操作,然後解鎖並離開臨界區。因為涉及到多個執行緒對全域性變數count進行操作,所以要用執行緒互斥鎖對count進行控制;所以首先定義互斥鎖mutex,然後呼叫pthread_mutex_lock(&mutex)進行上鎖,對count進行操作之後再呼叫pthread_mutex_unlock(&mutex)進行解鎖。

我們還希望對count的最大值進行控制,比如希望它的最大值是10;那麼當count等於10的時候,就要等待;

// for test

#include #include #include using namespace std;

int count = 0;

pthread_mutex_t mutex;

pthread_cond_t cond = pthread_cond_initializer;

void* produce(void* args)

++count;

cout << "producer is " << pthread_self() << " count is " << count << endl;

pthread_mutex_unlock(&mutex);

pthread_cond_signal(&cond);

}pthread_exit(nullptr);

}void* consume(void* args)

--count;

cout << "consumer is " << pthread_self() << " count is " << count << endl;

pthread_mutex_unlock(&mutex);

}pthread_exit(nullptr);

}int main()

pthread_detach(threadid_1);

pthread_detach(threadid_2);

getchar();

return 0;

}

互斥鎖和條件變數

互斥瑣 定義 指代相互排斥,最基本的同步形式。用於保護臨界區,以保證任何時刻只有乙個執行緒或乙個程序在執行其中的 上鎖 pthread mutex lock 臨界區解鎖 pthread mutex unlock 條件變數 定義 用於等待訊號,同步的另一種手段。每乙個條件變數總有乙個互斥瑣與之關聯。等...

互斥鎖和條件變數

mutex體現的是一種競爭,我離開了,通知你進來。cond體現的是一種協作,我準備好了,通知你開始吧。互斥鎖乙個明顯的缺點是它只有兩種狀態 鎖定和非鎖定。而條件變數通過允許執行緒阻塞和等待另乙個執行緒傳送訊號的方法彌補了互斥鎖的不足,它常和互斥鎖一起配合使用。使用時,條件變數被用來阻塞乙個執行緒,當...

互斥鎖和條件變數

條件變數 執行緒最大的特點就是資源的共享性,然而資源共享中的同步問題是多執行緒程式設計的難點。互斥鎖通過鎖機制來實現執行緒間的同步。使用互斥鎖前必須進行初始化操作。初始化有兩種方式 一種是靜態賦值法,將將巨集結構常量pthread mutex initializer賦給互斥鎖,操作語句如下 pthr...