Linux 多工程式設計 執行緒同步與互斥 讀寫鎖

2021-09-02 02:01:33 字數 3426 閱讀 6488

讀寫鎖基本原理

當有乙個執行緒已經持有互斥鎖時,互斥鎖將所有試圖進入臨界區的執行緒都阻塞住。但是考慮一種情形,當前持有互斥鎖的執行緒只是要讀訪問共享資源,而同時有其它幾個執行緒也想讀取這個共享資源,但是由於互斥鎖的排它性,所有其它執行緒都無法獲取鎖,也就無法讀訪問共享資源了,但是實際上多個執行緒同時讀訪問共享資源並不會導致問題。

在對資料的讀寫操作中,更多的是讀操作,寫操作較少,例如對資料庫資料的讀寫應用。為了滿足當前能夠允許多個讀出,但只允許乙個寫入的需求,執行緒提供了讀寫鎖來實現。

讀寫鎖的特點如下:

1)如果有其它執行緒讀資料,則允許其它執行緒執行讀操作,但不允許寫操作。

2)如果有其它執行緒寫資料,則其它執行緒都不允許讀、寫操作。

讀寫鎖分為讀鎖和寫鎖,規則如下:

1)如果某執行緒申請了讀鎖,其它執行緒可以再申請讀鎖,但不能申請寫鎖。

2)如果某執行緒申請了寫鎖,其它執行緒不能申請讀鎖,也不能申請寫鎖。

讀寫鎖基本操作

posix 定義的讀寫鎖的資料型別是: pthread_rwlock_t。

所需標頭檔案:#include

1)初始化讀寫鎖

int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); 

功能:用來初始化 rwlock 所指向的讀寫鎖。

引數:rwlock:指向要初始化的讀寫鎖指標。

attr:讀寫鎖的屬性指標。如果 attr 為 null 則會使用預設的屬性初始化讀寫鎖,否則使用指定的 attr 初始化讀寫鎖。

返回值:

成功:0,讀寫鎖的狀態將成為已初始化和已解鎖。

失敗:非 0 錯誤碼。

可以使用巨集 pthread_rwlock_initializer 靜態初始化讀寫鎖,比如:

pthread_rwlock_t my_rwlock = pthread_rwlock_initializer;

這種方法等價於使用 null 指定的 attr 引數呼叫 pthread_rwlock_init() 來完成動態初始化,不同之處在於pthread_rwlock_initializer 巨集不進行錯誤檢查

2)申請讀鎖

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock ); 

功能:以阻塞方式在讀寫鎖上獲取讀鎖(讀鎖定)。如果沒有寫者持有該鎖,並且沒有寫者阻塞在該鎖上,則呼叫執行緒會獲取讀鎖。如果呼叫執行緒未獲取讀鎖,則它將阻塞直到它獲取了該鎖。乙個執行緒可以在乙個讀寫鎖上多次執行讀鎖定。執行緒可以成功呼叫 pthread_rwlock_rdlock() 函式 n 次,但是之後該執行緒必須呼叫 pthread_rwlock_unlock() 函式 n 次才能解除鎖定。

引數:rwlock:讀寫鎖指標。

返回值:

成功:0

失敗:非 0 錯誤碼

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); 

用於嘗試以非阻塞的方式來在讀寫鎖上獲取讀鎖。如果有任何的寫者持有該鎖或有寫者阻塞在該讀寫鎖上,則立即失敗返回。

3)申請寫鎖

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock ); 

功能:在讀寫鎖上獲取寫鎖(寫鎖定)。如果沒有寫者持有該鎖,並且沒有寫者讀者持有該鎖,則呼叫執行緒會獲取寫鎖。如果呼叫執行緒未獲取寫鎖,則它將阻塞直到它獲取了該鎖。

引數:rwlock:讀寫鎖指標。

返回值:

成功:0

失敗:非 0 錯誤碼

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); 

用於嘗試以非阻塞的方式來在讀寫鎖上獲取寫鎖。如果有任何的讀者或寫者持有該鎖,則立即失敗返回。

4)解鎖

int pthread_rwlock_unlock (pthread_rwlock_t *rwlock); 

功能:無論是讀鎖或寫鎖,都可以通過此函式解鎖。

引數:rwlock:讀寫鎖指標。

返回值:

成功:0

失敗:非 0 錯誤碼

5)銷毀讀寫鎖

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

功能:用於銷毀乙個讀寫鎖,並釋放所有相關聯的資源(所謂的所有指的是由 pthread_rwlock_init() 自動申請的資源) 。

引數:rwlock:讀寫鎖指標。

返回值:

成功:0

失敗:非 0 錯誤碼

讀寫鎖應用例項

下面是乙個使用讀寫鎖來實現 4 個執行緒讀寫一段資料是例項。在此示例程式中,共建立了 4 個執行緒,其中兩個執行緒用來寫入資料,兩個執行緒用來讀取資料。當某個執行緒讀操作時,其他執行緒允許讀操作,卻不允許寫操作;當某個執行緒寫操作時,其它執行緒都不允許讀或寫操作。

示例**如下:

#include#include#includepthread_rwlock_t rwlock; //讀寫鎖

int num = 1;

//讀操作,其他執行緒允許讀操作,卻不允許寫操作

void *fun1(void *arg)} 

//讀操作,其他執行緒允許讀操作,卻不允許寫操作

void *fun2(void *arg)} 

//寫操作,其它執行緒都不允許讀或寫操作

void *fun3(void *arg)} 

//寫操作,其它執行緒都不允許讀或寫操作

void *fun4(void *arg)} 

int main()

執行結果如下:

Linux 多工程式設計 多工的同步與互斥

現代作業系統基本都是多工作業系統,即同時有大量可排程實體在執行。在多工作業系統中,同時執行的多個任務可能 這兩種情形是多工程式設計中遇到的最基本的問題,也是多工程式設計中的核心問題,同步和互斥就是用於解決這兩個問題的。互斥 是指散步在不同任務之間的若干程式片斷,當某個任務執行其中乙個程式片段時,其它...

Python 多工 執行緒同步

高階程式設計技巧 學習筆記 1.1 實現兩個執行緒一問一答 class xiaoai threading.thread def init self super init name 小艾同學 def run self print f 在 print f 你猜現在幾點了?class tianmao th...

多工 同步

實現多工之間通訊的最簡便的辦法是使用共享的資料結構。雖然共享資料區簡化了任務間的通訊,但是必須保證 每個任務在處理共享資料時的排他性。以避免競爭和資料破壞。共享資源滿足互斥性的一般方法有 1.關中斷,開中斷 2.使用測試並置位指令 3.禁止做任務切換 4.利用訊號量 一.關中斷 開中斷 這估計是最簡...