日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > Linux同步技術之讀寫鎖

Linux同步技術之讀寫鎖

來源:程序員人生   發布時間:2016-06-21 08:20:19 閱讀次數:2543次

互斥鎖試圖將想進入臨界區的所有線程都阻塞住,但是有時候該臨界區會觸及由這些線程同享的1個或多個數據的訪問或更新,這時候候我們就需要用到讀寫鎖

系統讀寫鎖的分配規則:
(1)只要有無線程持有給定的讀寫鎖用于寫,那末任意數量的線程可以持有該讀寫鎖用于讀。(系統規定寫鎖優先,但是可以更改成讀鎖優先)
(2)僅當沒有線程持有某個讀寫鎖用于讀或用于寫時,才能分配該讀寫鎖用于寫。

讀寫鎖用于讀稱為同享鎖,讀寫鎖用于寫稱為獨占鎖

讀寫鎖的獲得與釋放:
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
該函數獲得1個讀出鎖,如果對應的讀寫鎖已由某個寫入者持有,那就阻塞該調用線程。參數rwlock是讀寫鎖變量,類型為pthread_rwlock_t。

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
該函數嘗試獲得1個讀出鎖或寫入鎖,但是如果該所不能馬上取得,就返回1個EBUSY毛病,但是不阻塞調用線程。

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
該函數獲得1個寫入鎖,如果對應的讀寫鎖已由另外一個寫入者持有,或由1個或多個讀出者持有,就阻塞該調用線程。

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
該函數釋放1個讀出鎖或寫入鎖。

如果1個讀寫鎖是靜態分配的,即就是static pthread_rwlock_t rwlock,則其就初始化為PTHREAD_RWLOCK_INITIALIZER。

如果讀寫鎖是動態分配的,那就需要調用以下函數進行初始化和釋放!
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
讀寫鎖的動態燒毀函數。

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
const pthread_rwlockattr_t *restrict attr);
讀寫鎖的動態初始化函數。第2個參數是屬性,可以設置為NULL即就是使用默許屬性,若不希望使用默許屬性則可以通過調用系統的屬性的初始化和燒毀函數來設置和燒毀屬性。

以下是1個使用讀寫鎖的實現讀優先的例子:

//頭文件 #pragma once #include <unistd.h> #include <stdio.h> #include <pthread.h> #include <errno.h> typedef struct { pthread_mutex_t rw_mutex; pthread_cond_t rw_condreaders; pthread_cond_t rw_condwriters; int rw_magic; int rw_nwaitreaders; int rw_nwaitwriters; int rw_refcount; }my_pthread_rwlock_t; #define RW_MAGIC 0x19283746 #define MY_PTHREAD_RWLOCK_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,\ PTHREAD_COND_INITIALIZER,\ PTHREAD_COND_INITIALIZER,\ RW_MAGIC, 0, 0, 0} typedef int my_pthread_rwlockattr_t; int my_pthread_rwlock_init(my_pthread_rwlock_t *, my_pthread_rwlockattr_t *); int my_pthread_rwlock_rdlock(my_pthread_rwlock_t *); int my_pthread_rwlock_tryrdlock(my_pthread_rwlock_t *); int my_pthread_rwlock_wrlock(my_pthread_rwlock_t *); int my_pthread_rwlock_trywrlock(my_pthread_rwlock_t *); int my_pthread_rwlock_unlock(my_pthread_rwlock_t *); int my_pthread_rwlock_destroy(my_pthread_rwlock_t *); void clean_up(void *arg);
//讀寫鎖的初始化和燒毀函數 #include "pthread_rwlock.h" //讀寫鎖的初始化 int my_pthread_rwlock_init(my_pthread_rwlock_t *rw, my_pthread_rwlockattr_t *attr) { if(attr != NULL){ //屬性只有設置了NULL,若不為NULL則返回毛病 return(EINVAL); } int result; if((result = pthread_mutex_init(&rw->rw_mutex, NULL)) != 0){ //互斥鎖的初始化,成功返回0,失敗返回非0 return result; } if((result = pthread_cond_init(&rw->rw_condreaders, NULL)) != 0){ //初始化讀條件變量,成功返回0,失敗時燒毀互斥量 pthread_mutex_destroy(&rw->rw_mutex); } if((result = pthread_cond_init(&rw->rw_condwriters, NULL)) != 0){ //初始化寫條件變量,成功返回0,失敗時燒毀互斥量和讀條件變量 pthread_cond_destroy(&rw->rw_condreaders); pthread_mutex_destroy(&rw->rw_mutex); } rw->rw_nwaitreaders = 0; //初始化等待讀鎖的線程數 rw->rw_nwaitwriters = 0; //初始化等待寫鎖的線程數 rw->rw_refcount = 0; //初始化持有鎖的線程數 rw->rw_magic = RW_MAGIC; //初始化魔法數(魔法數可有可無,該數只是用來作判斷) return 0; } //讀寫鎖的燒毀 int my_pthread_rwlock_destroy(my_pthread_rwlock_t *rw) { if(rw->rw_magic != RW_MAGIC){ return (EINVAL); } if(rw->rw_refcount != 0 || rw->rw_nwaitreaders != 0 || rw->rw_nwaitwriters != 0){ //若持有鎖的線程數不為0,或等待讀鎖的線程數不為0,或等待寫鎖的線程數不為0,就返回BUSY; return (EBUSY); } pthread_mutex_destroy(&rw->rw_mutex); //燒毀互斥鎖 pthread_cond_destroy(&rw->rw_condreaders); //燒毀讀條件變量 pthread_cond_destroy(&rw->rw_condwriters); //燒毀寫條件變量 rw->rw_magic = 0; //魔法數賦0 return 0; }
//系統默許的寫鎖優先實現 int my_pthread_rint my_pthread_rwlock_rdlock(my_pthread_rwlock_t *rw) { int result; if(rw->rw_magic != RW_MAGIC){ return (EINVAL); } if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0){ //mutex_lock 保護臨界區域 return result; } while(rw->rw_refcount < 0 || rw->rw_nwaitwriters > 0){ //(寫優先)有線程持有鎖,或是寫等待的線程數大于0,即有寫線程在等待鎖時,讀線程數增加 rw->rw_nwaitreaders++; result = pthread_cond_wait(&rw->rw_condreaders, &rw->rw_mutex); //等待讀的線程被阻塞,當某時收到信號時,等待讀的線程被喚醒, 等待讀的線程數減少 rw->rw_nwaitreaders--; if(result != 0){ break; } } if(result == 0){ rw->rw_refcount++; //持有鎖的讀線程數增加,讀鎖是同享鎖,同時可有多個線程持有讀鎖 } pthread_mutex_unlock(&rw->rw_mutex); return result; } int my_pthread_rwlock_wrlock(my_pthread_rwlock_t *rw) { int result; if(rw->rw_magic != RW_MAGIC){ return EINVAL; } if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0){ return result; } while(rw->rw_refcount != 0){ //說明有線程正在持有鎖,所以等待加寫鎖的線程數增加 rw->rw_nwaitwriters++; result = pthread_cond_wait(&rw->rw_condwriters, &rw->rw_mutex); rw->rw_nwaitwriters--; if(result != 0){ break; } } if(result == 0){ //正常退出循環或未進入循環 rw->rw_refcount = -1; //有1個線程持有寫鎖,寫鎖是獨占鎖,每次只能有1個線程持有寫鎖 } pthread_mutex_unlock(&rw->rw_mutex); return result; } #endif int my_pthread_rwlock_unlock(my_pthread_rwlock_t *rw) { int result; if(rw->rw_magic != RW_MAGIC){ return EINVAL; } if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0){ return result; } if(rw->rw_refcount > 0){ //說明有線程持有讀鎖,解鎖是持有讀鎖的線程數減少 rw->rw_refcount--; }else if(rw->rw_refcount == -1){ //說明有1個線程持有寫鎖,解鎖完成后持有鎖的線程數為0,由于每次只會有1個線程持有寫鎖 rw->rw_refcount = 0; }else{ //沒有線程持有鎖,解鎖失敗 printf("unlock error.\n"); } //處理等待鎖的線程 if(rw->rw_nwaitwriters > 0){ //先處理等待寫的線程,由于是寫鎖優先 if(rw->rw_refcount == 0){ //若當前沒有線程持有鎖,則給等待寫鎖的線程發送1個信號,單播信號,每次只能有1個線程持有寫鎖 result = pthread_cond_signal(&rw->rw_condwriters); } }else if(rw->rw_nwaitreaders > 0){ //再處理等待讀的線程, result = pthread_cond_broadcast(&rw->rw_condreaders); //讀鎖是同享鎖,所以以廣播的方式給等待讀的線程發送信號,喚醒所有等待讀的線程 } pthread_mutex_unlock(&rw->rw_mutex); return result; }wlock_rdlock(my_pthread_rwlock_t *rw) { int result; if(rw->rw_magic != RW_MAGIC){ return (EINVAL); } if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0){ //mutex_lock 保護臨界區域 return result; } while(rw->rw_refcount < 0 || rw->rw_nwaitwriters > 0){ //(寫優先)有線程持有鎖,或是寫等待的線程數大于0,即有寫線程在等待鎖時,讀線程數增加 rw->rw_nwaitreaders++; result = pthread_cond_wait(&rw->rw_condreaders, &rw->rw_mutex); //等待讀的線程被阻塞,當某時收到信號時,等待讀的線程被喚醒, 等待讀的線程數減少 rw->rw_nwaitreaders--; if(result != 0){ break; } } if(result == 0){ rw->rw_refcount++; //持有鎖的讀線程數增加,讀鎖是同享鎖,同時可有多個線程持有讀鎖 } pthread_mutex_unlock(&rw->rw_mutex); return result; } int my_pthread_rwlock_wrlock(my_pthread_rwlock_t *rw) { int result; if(rw->rw_magic != RW_MAGIC){ return EINVAL; } if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0){ return result; } while(rw->rw_refcount != 0){ //說明有線程正在持有鎖,所以等待加寫鎖的線程數增加 rw->rw_nwaitwriters++; result = pthread_cond_wait(&rw->rw_condwriters, &rw->rw_mutex); rw->rw_nwaitwriters--; if(result != 0){ break; } } if(result == 0){ //正常退出循環或未進入循環 rw->rw_refcount = -1; //有1個線程持有寫鎖,寫鎖是獨占鎖,每次只能有1個線程持有寫鎖 } pthread_mutex_unlock(&rw->rw_mutex); return result; } #endif int my_pthread_rwlock_unlock(my_pthread_rwlock_t *rw) { int result; if(rw->rw_magic != RW_MAGIC){ return EINVAL; } if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0){ return result; } if(rw->rw_refcount > 0){ //說明有線程持有讀鎖,解鎖是持有讀鎖的線程數減少 rw->rw_refcount--; }else if(rw->rw_refcount == -1){ //說明有1個線程持有寫鎖,解鎖完成后持有鎖的線程數為0,由于每次只會有1個線程持有寫鎖 rw->rw_refcount = 0; }else{ //沒有線程持有鎖,解鎖失敗 printf("unlock error.\n"); } //處理等待鎖的線程 if(rw->rw_nwaitwriters > 0){ //先處理等待寫的線程,由于是寫鎖優先 if(rw->rw_refcount == 0){ //若當前沒有線程持有鎖,則給等待寫鎖的線程發送1個信號,單播信號,每次只能有1個線程持有寫鎖 result = pthread_cond_signal(&rw->rw_condwriters); } }else if(rw->rw_nwaitreaders > 0){ //再處理等待讀的線程, result = pthread_cond_broadcast(&rw->rw_condreaders); //讀鎖是同享鎖,所以以廣播的方式給等待讀的線程發送信號,喚醒所有等待讀的線程 } pthread_mutex_unlock(&rw->rw_mutex); return result; }
//自己設置的讀鎖優先的實現 int my_pthread_rwlock_unlock(my_pthread_rwlock_t *rw) //解鎖進程 { int result; if(rw->rw_magic != RW_MAGIC){ return EINVAL; } if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0){ //互斥鎖加鎖與解鎖之間構成臨界區 return result; } if(rw->rw_refcount > 0){ //說明持有讀鎖的線程數 > 0 rw->rw_refcount--; //將讀鎖的數量減1 }else if(rw->rw_refcount == -1){ //說明有1個線程持有讀鎖 rw->rw_refcount = 0; //解鎖以后持有鎖的線程數為0 }else{ //沒有線程持有鎖,解鎖失敗 printf("unlock error.\n"); } //處理等待加讀寫鎖的線程 if(rw->rw_nwaitreaders > 0){ //若等待加讀鎖的線程數>0,就廣播發送信號(讀鎖是同享鎖即每次可有多個線程加上讀鎖),使所有等待加讀鎖的線程全部加鎖 result = pthread_cond_broadcast(&rw->rw_condreaders); }else if(rw->rw_nwaitwriters > 0){ //若等到加寫鎖的線程>0,并且持有鎖的線程的個數為0,就單播發送信號,使得等待加寫鎖的線程中的1個線程被喚醒 if(rw->rw_refcount == 0){ result = pthread_cond_signal(&rw->rw_condwriters); } } pthread_mutex_unlock(&rw->rw_mutex); //解鎖互斥量 return result; } int my_pthread_rwlock_rdlock(my_pthread_rwlock_t *rw) //讀鎖實現 { int result; if(rw->rw_magic != RW_MAGIC){ return (EINVAL); } if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0){ //加鎖互斥量與解鎖互斥量構成臨界區 return result; } //讀鎖優先的實現 while(rw->rw_refcount != 0){ //說明有線程持有鎖 rw->rw_nwaitreaders++; //所以等待加讀鎖的線程數增加 pthread_cleanup_push(clean_up, NULL); result = pthread_cond_wait(&rw->rw_condreaders, &rw->rw_mutex); //等待加讀鎖的線程被阻塞,當某時收到加讀鎖信號的時候,等待加讀鎖的線程數減少 pthread_cleanup_pop(0); rw->rw_nwaitreaders--; if(result != 0){ break; } } if(result == 0){ //正常退出循環或未進入while循環 rw->rw_refcount++; //所有等待讀鎖的線程加鎖(讀鎖是同享鎖,同時可有多個線程加鎖成功) } pthread_mutex_unlock(&rw->rw_mutex); //解鎖互斥量 return result; } //讀鎖優先下的寫鎖實現 int my_pthread_rwlock_wrlock(my_pthread_rwlock_t *rw) { int result; if(rw->rw_magic != RW_MAGIC){ return EINVAL; } if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0){ return result; } while(rw->rw_refcount > 0 || rw->rw_nwaitreaders > 0){ //當持有鎖的線程數>0并且等待加讀鎖的線程數>0時,等待寫鎖的線程數加1 rw->rw_nwaitwriters++; pthread_cleanup_push(clean_up, NULL); result = pthread_cond_wait(&rw->rw_condwriters, &rw->rw_mutex); //等待加寫鎖的線程被阻塞,當某時收到可以加寫鎖的信號的時候,等待加寫鎖的1個線程被喚醒 pthread_cleanup_pop(0); rw->rw_nwaitwriters--; if(result != 0){ break; } } if(result == 0){ //while循環正常退出或未進入循環 rw->rw_refcount = -1; //1個線程持有寫鎖(寫鎖是獨占鎖,同1時刻只有1個線程持有寫鎖) } pthread_mutex_unlock(&rw->rw_mutex); //解鎖互斥量 return result; }
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 久久国产精品一区二区 | 蜜臀av在线播放一区二区三区 | 日日操夜夜操狠狠操 | 男操女在线观看 | 精品国产美女 | 日韩精品视频在线免费观看 | 二区三区在线 | 国产一区二区三区免费在线观看 | 欧美午夜精品一区二区三区电影 | 2015成人永久免费视频 | 国产精品网站在线观看 | 久久精品免费观看 | 欧美日韩高清在线一区 | 国产日韩欧美一区二区 | 男女爱爱免费视频 | 91—区二区国产好的精华液 | 国产成人精品一区二区三区四区 | 色欧美日韩 | 欧美黑人巨大久久久精品一区小蓝 | av在线网站观看 | 午夜性爽爽爽爽爱爱爱爱 | 黄a视频| 99热网站 | 在线国产一区二区 | 亚洲精品视频一区二区三区 | 在线麻豆视频 | 国产精品免费一区二区 | 在线一区二区国产 | 国产精品久久久久久久久久新婚 | 亚洲欧美综合久久 | 欧美精品中文字幕久久二区 | 成人免费乱码大片a毛片软件 | www.伊人.com| 天天草天天干 | 久久久久亚洲综合 | 亚洲国产精品视频 | 欧美视频一区二区 | 日韩精品一级毛片在线播放 | 国产传媒一区二区 | 欧美 日本 国产 | 少妇性bbb搡bbb爽爽爽欧美 |