日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【线程】读写锁

發布時間:2023/11/30 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【线程】读写锁 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、概念

一把讀寫鎖具備三種狀態:

  • 讀模式下加鎖狀態(讀鎖)
  • 寫模式下加鎖轉態(寫鎖)
  • 不加鎖狀態

2. 讀寫鎖特性:

  • 讀寫鎖是寫模式加鎖時,解鎖前,所有對該鎖加鎖的線程都會阻塞。
  • 讀寫鎖是讀模式加時,如果線程以讀模式加鎖會成功,如果線程以寫模式加鎖會阻塞
  • 讀寫鎖是讀模式加鎖時,既有試圖以寫模式加鎖的線程,也有試圖以讀模式加鎖的線程,那么讀模式會讀阻塞隨后的讀模式鎖請求,優先滿足寫模式鎖,讀鎖、寫鎖并行阻塞,寫鎖優先級高

讀寫鎖也叫共享_獨占鎖,當讀寫鎖以讀模式鎖住時,它以共享模式鎖住;當它以寫模式鎖住時,它是獨占鎖住的,寫獨占,讀共享


3. 讀寫鎖的特性:

線程A加讀鎖成功, 又來了三個線程, 做讀操作, 可以加鎖成功

  • 讀共享 - 并行處理

線程A加寫鎖成功, 又來了三個線程, 做讀操作, 三個線程阻塞

  • 寫獨占

線程A加讀鎖成功, 又來了B線程加寫鎖阻塞, 又來了C線程加讀鎖阻塞

  • 讀寫不能同時
  • 寫的優先級高

4. 讀寫鎖場景:

線程A加寫鎖成功, 線程B請求讀鎖

  • 線程B阻塞

線程A持有讀鎖, 線程B請求寫鎖

  • 線程B阻塞

線程A擁有讀鎖, 線程B請求讀鎖

  • 線程B加鎖成功

線程A持有讀鎖, 然后線程B請求寫鎖, 然后線程C請求讀鎖

  • B阻塞,c阻塞 - 寫的優先級高
  • A解鎖,B線程加寫鎖成功,C繼續阻塞
  • B解鎖,C加讀鎖成功

線程A持有寫鎖, 然后線程B請求讀鎖, 然后線程C請求寫鎖

  • BC阻塞
  • A解鎖,C加寫鎖成功,B繼續阻塞
  • C解鎖,B加讀鎖成功

二、主要函數

1. 函數原型:

#include <pthread.h> pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); 初始化讀寫鎖 pthread_rwlock_destroy(pthread_rwlock_t *rwlock); 銷毀讀寫鎖

2. 函數原型:阻塞版本

#include <pthread.h> int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); 讀鎖 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); 寫鎖 int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); 解鎖

?

三、程序清單

1. 測試代碼:

#include <stdio.h> #include <unistd.h> #include <pthread.h>int counter; //全局資源 pthread_rwlock_t rwlock;void *th_write(void *arg) {int t;int i = (int)arg;while (1) {t = counter;usleep(1000);pthread_rwlock_wrlock(&rwlock);printf("=======write %d: %lu: counter = %d ++counter = %d\n", i, pthread_self(), t, ++counter);pthread_rwlock_unlock(&rwlock);usleep(5000);}return NULL; }void *th_read(void *arg) {int t;int i = (int)arg;while (1) {pthread_rwlock_rdlock(&rwlock);printf("---------------read %d: %lu: %d\n", i, pthread_self(), counter);pthread_rwlock_unlock(&rwlock);usleep(900);}return NULL; }int main() {int i;pthread_t tid[8];pthread_rwlock_init(&rwlock, NULL);for (i = 0; i < 3; ++i)pthread_create(&tid[i], NULL, th_write, (void*)i);for (i = 0; i < 5; ++i)pthread_create(&tid[i + 3], NULL, th_read, (void*)i);for (i = 0; i < 8; ++i)pthread_join(tid[i], NULL);pthread_rwlock_destroy(&rwlock);return 0; }

輸出結果:

?

互斥鎖實現讀寫鎖
?

#include<pthread.h>pthread_mutex_t rdLock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t wrLock = PTHREAD_MUTEX_INITIALIZER; int readCnt = 0;//設置讀鎖調用次數的標志位//實現讀鎖(共享鎖) void rdLock() {pthread_mutex_lock(&rdLock);readCnt++;if (readCnt == 1)//有人讀,于是阻塞寫鎖pthread_mutex_lock(&wrLock);pthread_mutex_unlock(&rdLock); }void rdUnlock() {pthread_mutex_lock(&rdLock);readCnt--;if (readCnt == 0)//表示已沒有人在讀,釋放寫鎖,可以寫入了pthread_mutex_unlock(&wrLock);pthread_mutex_unlock(&rdLock); }void wrLock() {pthread_mutex_lock(&wrLcok); }void wrUnlock() {pthread_mutex_unlock(&wrLock); }

一、實驗項目

問題描述】程序 trainticket 中,有 100 個線程,其中 90 個線程是查余票數量的,只有 10 個線程搶票,每個線程一次買 10 張票。初始狀態下一共有 1000 張票。因此執行完畢后,還會剩下 900 張票。

程序 trainticket 在運行的時候需要傳入參數,即:

  • 參數 0:表示不加任何鎖
  • 參數 1:表示使用讀寫鎖
  • 參數 2:表示使用互斥量
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h>struct Ticket {int remain; // 余票數,初始化為 1000pthread_rwlock_t rwlock; // 讀寫鎖pthread_mutex_t mlock; // 互斥鎖,主要是為了和讀寫鎖進行對比 }ticket;// 通過命令行傳參數來取得這個值,用來控制到底使用哪一種鎖 // 0:不加鎖 1:加讀寫鎖 2:加互斥鎖 int lock = 0;void* query(void* arg) //查票線程 {int name = (int)arg;sleep(rand() % 5 + 1);if (lock == 1)pthread_rwlock_rdlock(&ticket.rwlock); // 讀模式加鎖else if (lock == 2)pthread_mutex_lock(&ticket.mlock);int remain = ticket.remain;sleep(1);printf("%03d query: %d\n", name, remain);if (lock == 1)pthread_rwlock_unlock(&ticket.rwlock);else if (lock == 2)pthread_mutex_unlock(&ticket.mlock);return NULL; }void* buy(void* arg) // 搶票線程 {int name = (int)arg;if (lock == 1)pthread_rwlock_wrlock(&ticket.rwlock); // 寫模式加鎖else if (lock == 2)pthread_mutex_lock(&ticket.mlock);int remain = ticket.remain;remain -= 10; // 一次買 10 張票sleep(1);ticket.remain = remain;printf("%03d buy 10 tickets\n", name);if (lock == 1)pthread_rwlock_unlock(&ticket.rwlock);else if (lock == 2)pthread_mutex_unlock(&ticket.mlock);sleep(rand() % 5 + 2);return NULL; }int main(int argc, char* argv[]) {lock = 0;if (argc >= 2) lock = atoi(argv[1]);int names[100];pthread_t tid[100];int i;for (i = 0; i < 100; ++i) names[i] = i;ticket.remain = 1000;printf("remain ticket = %d\n", ticket.remain);pthread_rwlock_init(&ticket.rwlock, NULL);pthread_mutex_init(&ticket.mlock, NULL);for (i = 0; i < 100; ++i) {if (i % 10 == 0)pthread_create(&tid[i], NULL, buy, (void*)names[i]);elsepthread_create(&tid[i], NULL, query, (void*)names[i]);}for (i = 0; i < 100; ++i) pthread_join(tid[i], NULL);pthread_rwlock_destroy(&ticket.rwlock);pthread_mutex_destroy(&ticket.mlock);printf("remain ticket = %d\n", ticket.remain);return 0; }

?

總結

以上是生活随笔為你收集整理的【线程】读写锁的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。