標籤:讀寫鎖 同步
概述
互斥鎖把試圖進入我們稱之為臨界區的所有其他線程都阻塞住。該臨界區通常涉及對由這些線程共用一個或多個資料的訪問或更新。讀寫鎖在擷取讀寫鎖用於讀某個資料和擷取讀寫鎖用於寫直接作區別。讀寫鎖的分配規則如下:
1、只要沒有線程持有某個給定的讀寫鎖用於寫,那麼任意數目的線程可以持有該讀寫鎖用於讀。
2、僅當沒有線程持有某個給定的讀寫鎖用於讀或用於寫時,才能分配該讀寫鎖用於寫。
即只要沒有線程在修改某個給定的資料,那麼任意數目的線程都可以擁有該資料的讀訪問權。僅當沒有其他線程在讀或修改某個給定的資料時,當前線程才可以修改它。
這種對於某個給定資源的共用訪問也稱為共用-獨佔上鎖,因為擷取一個讀寫鎖用於讀稱為共用鎖定,擷取一個讀寫鎖用於寫稱為獨佔鎖。
擷取與釋放讀寫鎖
讀寫鎖的資料類型為pthread_rwlock_t。如果這個類型的某個變數是靜態分配的,則可通過給它賦常值PTHREAD_RWLOCK_INITIALIZER來初始化它。
pthread_rwlock_rdlock擷取一個讀出鎖,如果對應的讀寫鎖已由某個寫入者持有,那就阻塞調用線程。pthread_rwlock_wrlock擷取一個寫入鎖,如果對應的讀寫鎖已由另一個寫入者持有,或者已由一個或多個讀出者持有,那就阻塞調用線程。pthread_rwlock_unlock釋放一個讀出鎖或寫入鎖。
#include <pthread.h>intpthread_rwlock_rdlock(pthread_rwlock_t *rwptr);intpthread_rwlock_wrlock(pthread_rwlock_t *rwptr);intpthread_rwlock_unlock(pthread_rwlock_t *rwptr); //成功返回0,出錯返回為正的EXXX值。
下面兩個函數嘗試擷取一個讀出鎖或寫入鎖,但如果該鎖不能馬上取得,那就返回一個EBUSY錯誤,而不是調用線程投入睡眠。
#include <pthread.h>intpthread_rwlock_tryrdlock(pthread_rwlock_t *rwptr);intpthread_rwlock_trywrlock(pthread_rwlock_t *rwptr); //成功返回0,出錯返回正值
讀寫鎖屬性
給靜態分配的讀寫鎖賦值PTHREAD_RWLOCK_INITIALIZER來初始化它。讀寫鎖變數也可通過調用pthread_rwlock_init來動態地初始化。噹噹一個線程不再需要某個讀寫鎖時,可調用pthread_rwlock_destroy摧毀它。
#include <pthread.h>int pthread_rwlock_init(pthread_rwlock_t *rwptr, const pthread_rwlockattr_t *attr);int pthread_rwlock_destroy(pthread_rwlock_t *rwptr);//成功為0,出錯為正值
初始化某個讀寫鎖時,如果attr是null 指標,就使用預設屬性。要賦予它非預設的屬性,需要使用如下兩個函數:
#include <pthread.h>int pthread_rwlockattr_init(pthread_rwlockattr_t *rwptr);int pthread_rwlockattr_destroy(pthread_rwlockattr_t *rwptr);//成功為0,出錯為正值
資料類型為pthread_rwlockattr_t的某個屬性對象一旦初始化,就通過調用不同的函數來啟用或禁止特定屬性。當前定義了的唯一屬性是PTHREAD_PROCESS_SHARED,它指定相應的讀寫鎖將不同進程間共用,而不僅僅是在單個進程內的不同線程間共用。以下兩個函數分別擷取和設定這個屬性。
#include <pthread.h>int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr, int *valptr);int pthread_rwlockattr_setpshared(const pthread_rwlockattr_t *attr, int value); //成功返回0,出錯返回正值
讀寫鎖的實現可參考《UNP2》P142