C实现读写锁
一、概述
案例:编写一个案例测试读写锁,要求:新建三个线程写,5个线程读,来测试读写锁。
读写锁的基本概念:
读写锁也叫共享-独占锁。当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的。写独占,读共享。
读写锁的使用场合:
对数据结构读的次数远大于写的情况
读写锁的特性:
1.读写锁是“写模式加锁”时,解锁前,所有对该锁加锁的线程都会被阻塞
2.读写锁是“读模式加锁”时,如果线程以读模式对其加锁会成功;如果线程以写模式加锁会阻塞。
3.读写锁是“读模式加锁”时, 既有试图以写模式加锁的线程,也有试图以读模式加锁的线程。那么读写锁会阻塞随后的读模式锁请求。优先满足写模式锁。读锁、写锁并行阻塞,写锁优先级高
读写锁场景练习:
1. 线程A加写锁成功, 线程B请求读锁
答:线程B阻塞
2.线程A持有读锁, 线程B请求写锁
答:线程B阻塞
3.线程A拥有读锁, 线程B请求读锁
答:线程B加锁成功
4.线程A持有读锁, 然后线程B请求写锁, 然后线程C请求读锁
答:B阻塞,c阻塞 - 写的优先级高
5.A解锁,B线程加写锁成功,C继续阻塞
答:B解锁,C加读锁成功
6.线程A持有写锁, 然后线程B请求读锁, 然后线程C请求写锁
答:BC阻塞
7.A解锁,C加写锁成功,B继续阻塞
答:C解锁,B加读锁成功
读写锁操作的基本步骤:
1.定义一把锁:pthread_rwlock_t rwlock;
2.初始化读写锁:pthread_rwlock_init()
3.加读锁:pthread_rwlock_rdlock()
4.加写锁:pthread_rwlock_wrlock()
5.解锁:pthread_rwlock_unlock();
6.释放锁:pthread_rwlock_destroy();
根据以上6步骤,下面看看具体的代码示例
二、代码示例
//读写锁测试程序 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include <pthread.h> //定义一个全局变量 int number = 0; //定义一把读写锁 pthread_rwlock_t rwlock; //写线程回调函数 void * thread_write(void *arg){ int i = *(int *)arg; int cur; while(1){ //加写锁 pthread_rwlock_wrlock(&rwlock); cur = number; cur++; number = cur; printf("[%d]-W:[%d]\n",i,cur); //解锁 pthread_rwlock_unlock(&rwlock); sleep(rand()%3); } } //读线程回调函数 void *thread_read(void *arg){ int i = *(int *)arg; int cur; while(1){ //加读锁 pthread_rwlock_rdlock(&rwlock); cur = number; printf("[%d]-R:[%d]\n",i,cur); //读写锁测试程序 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include <pthread.h> //定义一个全局变量 int number = 0; //定义一把读写锁 pthread_rwlock_t rwlock; //写线程回调函数 void * thread_write(void *arg){ int i = *(int *)arg; int cur; while(1){ //加写锁 pthread_rwlock_wrlock(&rwlock); cur = number; cur++; number = cur; printf("[%d]-W:[%d]\n",i,cur); //解锁 pthread_rwlock_unlock(&rwlock); sleep(rand()%3); } } //读线程回调函数 void *thread_read(void *arg){ int i = *(int *)arg; int cur; while(1){ //加读锁 pthread_rwlock_rdlock(&rwlock); cur = number; printf("[%d]-R:[%d]\n",i,cur); //解锁 pthread_rwlock_unlock(&rwlock); sleep(rand()%3); } } int main(){ int n = 8; int i =0; int arr[8]; //定义线程 id pthread_t thread[8]; //初始化读写锁 pthread_rwlock_init(&rwlock,NULL); //创建是哪个写锁 for(i=0;i<3;i++){ arr[i] = i; //创建写线程 pthread_create(&thread[i],NULL,thread_write,&arr[i]); } //创建5个读线程 for(i=3;i<n;i++){ arr[i] = i; //创建读线程 pthread_create(&thread[i],NULL,thread_read,&arr[i]); } //回收子线程 int j = 0; for(j=0;j<n;j++){ pthread_join(thread[j],NULL); } //释放锁 pthread_rwlock_destroy(&rwlock); return 0; }
三、示例图
如下图所示:读出来的数据永远是写入的最后一个数据。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探