1. 程式人生 > >程序間通訊學習筆記-互斥鎖 && 讀寫鎖

程序間通訊學習筆記-互斥鎖 && 讀寫鎖

第七章 互斥鎖和條件變數

互斥鎖是用於保護臨界區的,實際上是保護在臨界區中被操縱的資料,保護多個執行緒或者多個程序的共享資料。

#include<pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mptr);
int pthread_mutex_trylock(pthread_mutex_t *mptr);
int pthread_mutex_unlock(pthread_mutex_t *mptr);

如果互斥鎖已被其他執行緒佔據了,那麼pthread_mutex_lock將阻塞直到互斥鎖被解鎖。第二個函式在這種情況下,會返回一個EBUSY錯誤。

如果互斥鎖是靜態分配 的,可以用PTHREAD_MUTEX_INITIALIZER初始化為常量。如果互斥鎖是動態分配的,就要用pthread_mutex_init()函式初始化。

對比上鎖與等待
這個例子中,所有生產者執行緒都啟動後,立即啟動消費者執行緒。所以對消費者進行了改動,要判斷當前消費的i是否已經生產好了。每次對共享資料進行訪問時,都要申請互斥鎖。

條件變數:等待與訊號傳送
互斥鎖用於上鎖,條件變數用於等待

#include<pthread.h>
int pthread_cond_wait(pthread_cond_t *cptr,pthread_mutex_t *mptr
); int pthread_cond_signal(pthread_cond_t *cptr);

pthread_cond_wait等待某個條件為真時。這個函式原子地執行以下兩步:

  • 給互斥鎖解鎖
  • 把呼叫執行緒投入睡眠,知道另外其某個執行緒就本條件變數呼叫pthread_cond_signal函式

然後在這個函式返回前,對互斥鎖進行上鎖,修改共享資料,然後對互斥鎖進行解鎖

7.6 條件變數:定時等待和廣播
單播和廣播,根據滿足條件後,要喚醒因為此條件而阻塞所有執行緒,還是一個等待執行緒而採用廣播和單播發送。

#include<pthread.h>
int pthread_cond_broadcast(pthread_cond_t *cptr
); int pthread_cond_timedwait(pthread_cond_t *cptr,pthread_mutex_t *mptr, const struct timespec *abstime);

pthread_cond_timedwait函式執行緒就阻塞時間設定一個限制值。如果發生超時,就返回ETIMEDOUT錯誤
時間值是絕對時間

7.7 互斥鎖和條件變數的屬性

#include<pthread.h>
int pthread_mutex_init(pthread_mutex_t *mptr, const pthread_mutexattr_t *attr);
int pthread_mutex_destroy(pthread_mutex_t *mptr);
int pthread_cond_init(pthread_cond_t *cptr,pthread_condattr_t *attr);
int pthread_cond_destroy(pthread_cond_t *cptr);

互斥變數和條件變數用以上函式進行初始化和摧毀

#include<pthread.h>
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
int pthread_condattr_init(pthread_condattr_t *attr);
int pthread_condattr_destroy(pthread_condattr_t *attr);

以上函式是對互斥鎖、條件變數的屬性進行初始化和摧毀

第八章 讀寫鎖

讀寫鎖的分配規則:

  • 沒有執行緒持有某個給定的讀寫鎖用於寫,就可以有任意數目的執行緒持有讀寫鎖用於讀
  • 僅當沒有執行緒持有某個給定的讀寫鎖用於讀或用於學,才能分配這個讀寫鎖用於寫

    這種對於給定資源的共享訪問稱為共享-獨佔上鎖。對於讀是共享鎖,對於寫是獨佔鎖

#include<pthread.h>
int pthread_rwlock_rdlock(pthread_rwlock_t *rwptr);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwptr);
int pthread_rwlock_unlock(pthread_rwlock_t *rwptr);

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwptr);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwptr);

int pthread_rwlock_init(pthread_rwlock_t *rwptr,const pthread_rwlockattr_t *attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwptr);

int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr);

執行緒取消

#include<pthread.h>
int pthread_cancel(pthraed_t pid);

void pthread_cleanup_push(void (*func)(void*),void *arg);
void pthread_cleanup_pop(int execute);

通過由對方呼叫函式pthread_cancel,一個執行緒可以被同一個程序內的任何其他執行緒所取消(cancel)
清理處理晨旭可以恢復任何需要恢復的狀態。push函式中func引數是呼叫執行緒被取消是所呼叫的函式的地址。pop函式是刪除呼叫執行緒的取消清理棧中位於在山頂的函式中的execute引數不為0時,就是呼叫這個函式、