【linux系统编程】读写锁

【linux系统编程】读写锁

读写锁工作原理

  • 当「写锁」没有被线程持有时,多个线程能够并发地持有读锁,这大大提高了共享资源的访问效率,因为「读锁」是用于读取共享资源的场景,所以多个线程同时持有读锁也不会破坏共享资源的数据。
  • 但是,一旦「写锁」被线程持有后,读线程的获取读锁的操作会被阻塞,而且其他写线程的获取写锁的操作也会被阻塞。

APUE摘引

​ 当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是任何希望以写模式对此锁进行加锁的线程都会阻塞,直到所有的线程释放它们的读锁为止。虽然各操作系统对读写锁的实现各不相同,但当读写锁处于读模式锁住的状态,而这时有一个线程试图以写模式获取锁时,读写锁通常会阻塞随后的读模式锁请求。这样可以避免读模式锁长期占用,而等待的写模式锁请求一直得不到满足。
​ 读写锁非常适合于对数据结构读的次数远大于写的情况。当读写锁在写模式下时,它所保护的数据结构就可以被安全地修改,因为一次只有一个线程可以在写模式下拥有这个锁。当读写锁在读模式下时,只要线程先获取了读模式下的读写锁,该锁所保护的数据结构就可以被多个获得读模式锁的线程读取。
​ 读写锁也叫做共享互斥锁(shared-exclusive lock)。当读写锁是读模式锁住时,就可以说成是以共享模式锁住的。当它是写模式锁住的时候,就可以说成是以互斥模式锁住的。

摘自第三版11.6.4

读写优先级

另外,根据实现的不同,读写锁可以分为「读优先锁」和「写优先锁」。

  • 读优先锁期望的是,读锁能被更多的线程持有,以便提高读线程的并发性,它的工作方式是:当读线程A先持有了读锁,写线程B在获取写锁的时候,会被阻塞,并且在阻塞过程中,后续来的读线程C仍然可以成功获取读锁,最后直到读线程A和C释放读锁后,写线程B才可以成功获取写锁。如下图:

在这里插入图片描述

  • 而写优先锁是优先服务写线程,其工作方式是:当读线程A先持有了读锁,写线程B在获取写锁的时候,会被阻塞,并且在阻塞过程中,后续来的读线程∈获取读锁时会失败,于是读线程C将被阻塞在获取读锁的操作,这样只要读线程A释放读锁后,写线程B就可以成功获取读锁。如下图:

在这里插入图片描述

​ 读优先锁对于读线程并发性更好,但也不是没有问题。我们试想一下,如果一直有读线程获取读锁,那么写线程将永远获取不到写锁,这就造成了写线程「饥饿」的现象。

​ 写优先锁可以保证写线程不会饿死,但是如果一直有写线程获取写锁,读线程也会被「饿死」。

​ 既然不管优先读锁还是写锁,对方可能会出现饿死问题,那么我们就不偏袒任何一方,搞个「公平读写锁」。

公平读写锁比较简单的一种方式是:用队列把获取锁的线程排队,不管是写线程还是读线程都按照先进先出的原则加锁即可,这样读线程仍然可以并发,也不会出现「饥饿」的现象。

读写优先级部分摘自点这里跳转

调整读写优先级

通过修改读写锁的属性调整优先级

//写优先
pthread_rwlockattr_t attr;
pthread_rwlockattr_init(&attr);
pthread_rwlockattr_setkind_np (&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);	
//PTHREAD_RWLOCK_PREFER_READER_NP		//将上句中的宏替换为这即为读优先
(void)pthread_rwlock_init(&rwlock, &attr);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值