读写锁pthread_rwlock_t的使用

本文深入探讨了读写锁的概念、形式、操作及其与互斥锁的区别,详细介绍了如何使用读写锁解决读者写者问题,并通过实例展示了读写锁在实际应用中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文转自:http://blog.youkuaiyun.com/wonderisland/article/details/16940925


读写锁是用来解决读者写者问题的,读操作可以共享,写操作是排他的,读可以有多个在读,写只有唯一个在写,同时写的时候不允许读。


具有强读者同步和强写者同步两种形式

强读者同步:当写者没有进行写操作,读者就可以访问;

强写者同步:当所有写者都写完之后,才能进行读操作,读者需要最新的信息,一些事实性较高的系统可能会用到该所,比如定票之类的。


读写锁的操作:

读写锁的初始化:

        定义读写锁:          pthread_rwlock_t  m_rw_lock;

        函数原型:              pthread_rwlock_init(pthread_rwlock_t * ,pthread_rwattr_t *);

        返回值:0,表示成功,非0为一错误码

读写锁的销毁:

        函数原型:             pthread_rwlock_destroy(pthread_rwlock_t* );

        返回值:0,表示成功,非0表示错误码

获取读写锁的读锁操作:分为阻塞式获取和非阻塞式获取,如果读写锁由一个写者持有,则读线程会阻塞直至写入者释放读写锁。

        阻塞式:

                            函数原型:pthread_rwlock_rdlock(pthread_rwlock_t*);

        非阻塞式:

                            函数原型:pthread_rwlock_tryrdlock(pthread_rwlock_t*);

       返回值: 0,表示成功,非0表示错误码,非阻塞会返回ebusy而不会让线程等待

获取读写锁的写锁操作:分为阻塞和非阻塞,如果对应的读写锁被其它写者持有,或者读写锁被读者持有,该线程都会阻塞等待。

      阻塞式:

                           函数原型:pthread_rwlock_wrlock(pthread_rwlock_t*);

      非阻塞式:

                           函数原型:pthread_rwlock_trywrlock(pthread_rwlock_t*);

       返回值: 0,表示成功

释放读写锁:

                         函数原型:pthread_rwlock_unlock(pthread_rwlock_t*);

总结(转):

互斥锁与读写锁的区别:

当访问临界区资源时(访问的含义包括所有的操作:读和写),需要上互斥锁;

当对数据(互斥锁中的临界区资源)进行读取时,需要上读取锁,当对数据进行写入时,需要上写入锁。

读写锁的优点:

对于读数据比修改数据频繁的应用,用读写锁代替互斥锁可以提高效率。因为使用互斥锁时,即使是读出数据(相当于操作临界区资源)都要上互斥锁,而采用读写锁,则可以在任一时刻允许多个读出者存在,提高了更高的并发度,同时在某个写入者修改数据期间保护该数据,以免任何其它读出者或写入者的干扰。

读写锁描述:

获取一个读写锁用于读称为共享锁,获取一个读写锁用于写称为独占锁,因此这种对于某个给定资源的共享访问也称为共享-独占上锁。

有关这种类型问题(多个读出者和一个写入者)的其它说法有读出者与写入者问题以及多读出者-单写入者锁。

#include <stdio.h> #include <pthread.h> #include <unistd.h> //临界资源,应该使用volatile进行修饰,防止编译器对该变量进行优化 volatile int data = 10; //读写锁对象,必须是全局变量 pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; //子线程B的任务,格式是固定的 void * task_B(void *arg) { //线程任务应该是死循环,并且不会退出 while(1) { //获取读操作的锁 pthread_rwlock_rdlock(&rwlock); //对临界资源进行读操作 printf("I am Thread_B,data = %d\n",data); sleep(1); //释放读操作的锁 pthread_rwlock_unlock(&rwlock); } } //子线程C的任务,格式是固定的 void * task_C(void *arg) { //线程任务应该是死循环,并且不会退出 while(1) { //获取读操作的锁 pthread_rwlock_rdlock(&rwlock); //对临界资源进行读操作 printf("I am Thread_C,data = %d\n",data); sleep(1); //释放读操作的锁 pthread_rwlock_unlock(&rwlock); } } //主线程 A int main(int argc, char const *argv[]) { //1.对创建的读写锁对象进行初始化 pthread_rwlock_init(&rwlock,NULL); //2.创建子线程 pthread_t thread_B; pthread_t thread_C; pthread_create(&thread_B,NULL,task_B,NULL); pthread_create(&thread_C,NULL,task_C,NULL); //3.进入死循环,主线程需要对临界资源进行修改 while(1) { //主线程会阻塞等待,10s会解除阻塞 sleep(10); //获取写操作的锁 pthread_rwlock_wrlock(&rwlock); //对临界资源进行读操作 data += 20; printf("I am main_Thread,data = %d\n",data); sleep(5); //释放写操作的锁 pthread_rwlock_unlock(&rwlock); } return 0; }
最新发布
07-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值