多執行緒程式設計——讀寫鎖
一、什麼是讀寫鎖
讀寫鎖(也叫共享-獨佔鎖)實際是一種特殊的自旋鎖,它把對共享資源的訪問者劃分成讀者和寫者,讀者只對共享資源進行讀訪問,寫者則需要對共享資源進行寫操作。這種鎖相對於自旋鎖而言,能提高併發性,因為在多處理器系統中,它允許同時有多個讀者來訪問共享資源,最大可能的讀者數為實際的邏輯CPU數。寫者是排他性的,一個讀寫鎖同時只能有一個寫者或多個讀者(與CPU數相關),但不能同時既有讀者又有寫者。
如果讀寫鎖當前沒有讀者,也沒有寫者,那麼寫者可以立刻獲得讀寫鎖,否則它必須“自旋”在那裡,直到沒有任何寫者或讀者。如果讀寫鎖沒有寫者,那麼讀者可以立即獲得該讀寫鎖,否則讀者必須“自旋”在那裡,直到寫者釋放該讀寫鎖。讀寫鎖適合於對資料結構的讀次數比寫次數多很多的場合。
二、示例程式碼
#include <pthread.h> #include <unistd.h> #include <stdio.h> /* 執行緒控制塊 */ static pthread_t reader1; static pthread_t reader2; static pthread_t writer1; /* 共享資料book */ static int book = 0; /* 讀寫鎖 */ static pthread_rwlock_t rwlock; /* 函式結果檢查 */ static void check_result(char* str,int result) { if (0 == result) { printf("%s successfully!\n",str); } else { printf("%s failed! error code is %d\n",str,result); } } /*執行緒入口*/ static void* reader1_entry(void* parameter) { int i = 0; //pthread_detach(pthread_self()); while (1) { if(i++%5<2)//讀2秒,停3秒。讓寫可獲得鎖,否則讀執行緒一直鎖著,將無法寫 { pthread_rwlock_rdlock(&rwlock); /* 嘗試讀鎖定該讀寫鎖 */ printf("reader1 read book value is %d\n",book); sleep(1); /* 執行緒休眠2秒,切換到其他執行緒執行 */ pthread_rwlock_unlock(&rwlock); /* 執行緒執行後對讀寫鎖解鎖 */ }else { sleep(1); } } } static void* reader2_entry(void* parameter) { int i = 0; //pthread_detach(pthread_self()); while (1) { if(i++%5<2) { pthread_rwlock_rdlock(&rwlock); /* 嘗試讀鎖定該讀寫鎖 */ printf("reader2 read book value is %d\n",book); sleep(1); /* 執行緒休眠2秒,切換到其他執行緒執行 */ pthread_rwlock_unlock(&rwlock); /* 執行緒執行後對讀寫鎖解鎖 */ }else { sleep(1); /* 執行緒休眠2秒,切換到其他執行緒執行 */ } } } static void* writer1_entry(void* parameter) { //pthread_detach(pthread_self()); while (1) { //printf("writer1 \r\n"); if(!pthread_rwlock_trywrlock(&rwlock)) /* 嘗試寫鎖定該讀寫鎖 */ { book++; printf("writer1 write book value is %d\n",book); pthread_rwlock_unlock(&rwlock); /* 對讀寫鎖解鎖 */ sleep(1); /* 執行緒休眠2秒,切換到其他執行緒執行 */ }else { printf("Be BUSY ,can`t write now\r\n"); sleep(1); } } } /* 使用者應用入口 */ int application_init() { int result; /* 預設屬性初始化讀寫鎖 */ pthread_rwlock_init(&rwlock,NULL); /*建立writer1執行緒,執行緒入口是writer1_entry, 執行緒屬性為,入口引數為NULL*/ result = pthread_create(&writer1,NULL,writer1_entry,NULL); check_result("writer1 created",result); /*建立reader1執行緒,執行緒入口是reader1_entry, 執行緒屬性為預設值,入口引數為NULL*/ result = pthread_create(&reader1,NULL,reader1_entry,NULL); check_result("reader1 created",result); /*建立reader2執行緒,執行緒入口是reader2_entry, 執行緒屬性為預設值,入口引數為NULL*/ result = pthread_create(&reader2,NULL,reader2_entry,NULL); check_result("reader2 created",result); return 0; } int main() { int i ; application_init(); i=100; do{ sleep(1); }while(i--); }
執行結果:
-bash-3.2$ !g
gcc -pthread rwlock.c -o app
-bash-3.2$ ./app
writer1 created successfully!
reader1 created successfully!
reader2 created successfully!
writer1 write book value is 1
reader1 read book value is 1
reader2 read book value is 1
Be BUSY ,cant write now
reader1 read book value is 1
reader2 read book value is 1
Be BUSY ,cant write now
writer1 write book value is 2
writer1 write book value is 3
reader2 read book value is 3
reader1 read book value is 3
Be BUSY ,cant write now
reader2 read book value is 3
reader1 read book value is 3
Be BUSY ,cant write now
writer1 write book value is 4
writer1 write book value is 5
writer1 write book value is 6
reader2 read book value is 6
reader1 read book value is 6
Be BUSY ,cant write now
reader2 read book value is 6
reader1 read book value is 6
Be BUSY ,cant write now
writer1 write book value is 7
writer1 write book value is 8
writer1 write book value is 9
reader2 read book value is 9
Be BUSY ,can`t write now
reader1 read book value is 9