物聯網學習教程——執行緒同步與互斥:讀寫鎖

千鋒教育官方發表於2019-09-24


執行緒同步與互斥:讀寫鎖

讀寫鎖基本原理

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

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

 

讀寫鎖的特點如下:

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

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

 

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

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

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

 

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

讀寫鎖基本操作

以下函式所需標頭檔案:

#include <pthread.h>  

1)初始化讀寫鎖

 

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

功能:

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

引數:

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

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

可以使用宏 PTHREAD_RWLOCK_INITIALIZER 靜態初始化讀寫鎖,比如:

pthread_rwlock_t my_rwlock = PTHREAD_RWLOCK_INITIALIZER;

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

返回值:

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

失敗:非 0 錯誤碼。

 

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<stdio.h>  

#include<unistd.h>  

#include<pthread.h>  

  

pthread_rwlock_t rwlock; //讀寫鎖  

int num = 1;   

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

void *fun1(void *arg)  

{  

    while(1)  

    {  

        pthread_rwlock_rdlock(&rwlock);  

        printf("read num first===%d\n",num);  

        pthread_rwlock_unlock(&rwlock);  

        sleep(1);  

    }  

}    

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

void *fun2(void *arg)  

{  

    while(1)  

    {  

        pthread_rwlock_rdlock(&rwlock);  

        printf("read num second===%d\n",num);  

        pthread_rwlock_unlock(&rwlock);  

        sleep(2);  

    }  

}    

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

void *fun3(void *arg)  

{  

    while(1)  

    {  

          

        pthread_rwlock_wrlock(&rwlock);  

        num++;  

        printf("write thread first\n");  

        pthread_rwlock_unlock(&rwlock);  

        sleep(2);  

    }  

}    

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

void *fun4(void *arg)  

{  

    while(1)  

    {  

          

        pthread_rwlock_wrlock(&rwlock);  

        num++;  

        printf("write thread second\n");  

        pthread_rwlock_unlock(&rwlock);  

        sleep(1);  

    }  

}    

int main()  

{  

    pthread_t ptd1, ptd2, ptd3, ptd4;   

    pthread_rwlock_init(&rwlock, NULL);//初始化一個讀寫鎖  

      

    //建立執行緒  

    pthread_create(&ptd1, NULL, fun1, NULL);  

    pthread_create(&ptd2, NULL, fun2, NULL);  

    pthread_create(&ptd3, NULL, fun3, NULL);  

    pthread_create(&ptd4, NULL, fun4, NULL);  

      

    //等待執行緒結束,回收其資源  

    pthread_join(ptd1,NULL);  

    pthread_join(ptd2,NULL);  

    pthread_join(ptd3,NULL);  

    pthread_join(ptd4,NULL);  

      

    pthread_rwlock_destroy(&rwlock);//銷燬讀寫鎖  

      

    return 0;  

}  

執行結果如下:

 

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69914734/viewspace-2658094/,如需轉載,請註明出處,否則將追究法律責任。

相關文章