Linux多线程的同步------读写锁
前面介紹過Linux多線程同步的另外兩個方法------互斥鎖和信號量
Linux多線程的同步-----信號量和互斥鎖_神廚小福貴!的博客-CSDN博客
下面來看一下讀寫鎖:
? ? ? ? 讀寫鎖和互斥鎖都帶有一個鎖,那么他們有什么區(qū)別呢?
| 讀寫鎖 | 互斥鎖 |
| 多個讀操作可以同時進行 | 一次只有一個線程擁有互斥鎖,其他線程只有等待 |
| 寫操作之間必須互斥 | |
| 讀寫操作之間也是互斥的,且寫操作的應(yīng)優(yōu)先于讀操作(寫操作執(zhí)行的時候,其他函數(shù)都在阻塞) |
上面說到了讀寫鎖和互斥鎖的區(qū)別,相信大家對讀寫鎖已經(jīng)有了一定的理解,下面來看讀寫鎖所用到的函數(shù)以及頭文件:
頭文件:#include <pthread.h>?
讀寫鎖初始化函數(shù):
int pthread_rwlock_init(pthread_rwlock_t *rwlock, pthread_rwlockattr_t *attr);?
第一個參數(shù)是讀寫鎖指針,第二個參數(shù)是讀寫鎖的屬性的指針(一般置為NULL)----下面附上官方手冊
?讀鎖:int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);?
寫鎖:int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);?
解鎖:int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);?
銷毀鎖:int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);?
函數(shù)里面的參數(shù)都是所創(chuàng)建的讀寫鎖的指針
下面來看一個代碼示例:下面代碼是沒有加讀寫鎖🔓的代碼
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>pthread_rwlock_t rwlock;//讀寫鎖的創(chuàng)建void * read_fun1(void * arg) //讀子線程的函數(shù)
{while(1){printf("read1 start \n");sleep(1);printf("read2 end \n");}
}
void * read_fun2(void * arg)
{while(1){printf("read2 start \n");sleep(1);printf("read2 end \n");}
}void * write_fun(void * arg)
{while(1){printf("write start \n");sleep(1);printf("write end \n");}
}int main()
{pthread_rwlock_init(&rwlock,NULL);pthread_t idr1,idr2; //創(chuàng)建兩個讀的線程pthread_t idw; //創(chuàng)建一個寫的線程pthread_create(&idr1,NULL,read_fun1,NULL);pthread_create(&idr2,NULL,read_fun2,NULL);pthread_create(&idw,NULL,write_fun,NULL);pthread_join(idr1,NULL);pthread_join(idr2,NULL);pthread_join(idw,NULL);pthread_rwlock_destroy(&rwlock);exit(0);
}
~
上面代碼沒有加讀寫鎖,我們來運行結(jié)果:
?運行結(jié)果可看出,在讀操作進行的同時,寫操作也在進行著,那么我們再來看一下加了讀寫鎖之后的運行結(jié)果
來看加了讀寫鎖之后的代碼:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>pthread_rwlock_t rwlock;//讀寫鎖的創(chuàng)建void * read_fun1(void * arg) //讀子線程的函數(shù)
{while(1){pthread_rwlock_rdlock(&rwlock); //對讀操作枷鎖printf("read1 start \n");sleep(1);printf("read2 end \n");pthread_rwlock_unlock(&rwlock); //讀完進行解鎖}
}
void * read_fun2(void * arg)
{while(1){pthread_rwlock_rdlock(&rwlock); //對讀操作枷鎖printf("read2 start \n");sleep(1);printf("read2 end \n");pthread_rwlock_unlock(&rwlock); //讀完進行解鎖}
}void * write_fun(void * arg)
{while(1){pthread_rwlock_wrlock(&rwlock); //對寫操作枷鎖printf("write start \n");sleep(1);printf("write end \n");pthread_rwlock_unlock(&rwlock); //寫完進行解鎖}
}int main()
{pthread_rwlock_init(&rwlock,NULL);pthread_t idr1,idr2; //創(chuàng)建兩個讀的線程pthread_t idw; //創(chuàng)建一個寫的線程pthread_create(&idr1,NULL,read_fun1,NULL);pthread_create(&idr2,NULL,read_fun2,NULL);pthread_create(&idw,NULL,write_fun,NULL);pthread_join(idr1,NULL);pthread_join(idr2,NULL);pthread_join(idw,NULL);pthread_rwlock_destroy(&rwlock);exit(0);
}
~
加了鎖之后再來運行? ?看結(jié)果:
?看了結(jié)果發(fā)現(xiàn),誒,怎么還是不對啊,怎么沒有寫操作呢?
在我上面的代碼中,是讀操作的線程創(chuàng)建函數(shù)先于寫操作的線程創(chuàng)建函數(shù),然后剛開始就是讀拿鎖,又因為讀操作是可以同時拿鎖的,所以兩個讀操作同時拿鎖,中間可能會有間隔 ,但是這個間隔時間之中是另外一個讀操作在拿鎖,所以寫操作就一直拿不到鎖,但是你只要給每次解鎖之后加個睡眠一秒鐘的函數(shù),就會改善這種情況
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>pthread_rwlock_t rwlock;//讀寫鎖的創(chuàng)建void * read_fun1(void * arg) //讀子線程的函數(shù)
{while(1){pthread_rwlock_rdlock(&rwlock); //對讀操作枷鎖printf("read1 start \n");sleep(1);printf("read2 end \n");pthread_rwlock_unlock(&rwlock); //讀完進行解鎖sleep(1);}
}
void * read_fun2(void * arg)
{while(1){pthread_rwlock_rdlock(&rwlock); //對讀操作枷鎖printf("read2 start \n");sleep(1);printf("read2 end \n");pthread_rwlock_unlock(&rwlock); //讀完進行解鎖sleep(1);}
}void * write_fun(void * arg)
{while(1){pthread_rwlock_wrlock(&rwlock); //對寫操作枷鎖printf("write start \n");sleep(1);printf("write end \n");pthread_rwlock_unlock(&rwlock); //寫完進行解鎖sleep(1);}
}int main()
{pthread_rwlock_init(&rwlock,NULL);pthread_t idr1,idr2; //創(chuàng)建兩個讀的線程pthread_t idw; //創(chuàng)建一個寫的線程pthread_create(&idr1,NULL,read_fun1,NULL);pthread_create(&idr2,NULL,read_fun2,NULL);pthread_create(&idw,NULL,write_fun,NULL);pthread_join(idr1,NULL);pthread_join(idr2,NULL);pthread_join(idw,NULL);pthread_rwlock_destroy(&rwlock);exit(0);
}
加上睡眠函數(shù)之后的運行結(jié)果:
?就可以了,這是因為在讀完數(shù)據(jù)之后,間隔那一秒鐘,讀操作空閑不拿鎖的時候,那個寫操作就可以拿到鎖子,但是這玩意說到底的優(yōu)先級是什么,別人做過實驗,結(jié)果是寫操作優(yōu)先:
讀寫鎖的一個奇怪表現(xiàn) - 付哲 - 博客園
總結(jié)
以上是生活随笔為你收集整理的Linux多线程的同步------读写锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 线程安全之strtok()函数
- 下一篇: Linux多线程同步------条件变量