读写锁之ReentrantReadWriteLock与邮戳锁StampedLock知识总结

本文深入探讨了Java中的读写锁ReentrantReadWriteLock,包括其公平性选择、可重入特性和锁降级机制。同时,它与ReentrantLock的比较揭示了在读多写少场景下的优势。此外,文章提到了邮戳锁StampedLock,它是为了解决ReentrantReadWriteLock的写锁饥饿问题,提供了乐观读锁和悲观读写锁的选项。尽管StampedLock有其局限性,如不支持锁重入和条件变量,但它为并发控制提供了更多灵活性。

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

 ReentrantReadWriteLock

读写锁ReentrantReadWriteLock下,一个资源可以被多个读线程访问或一个写线程访问,但不能同时存在读写线程,也就是读读共享,读写互斥。多线程并发可以访问大面积的可以容许多个线程来读取,相对于ReentrantLock来说,ReentrantReadWriteLock更适用于读多写少的场景,但在写操作的时候二者性能是相差不多的,在ReentrantReadWriteLock中,可以一块使用读锁和写锁,但是需要先获取写锁,获取读锁,再释放写锁,释放读锁,通过锁降级来实现,但如果顺序颠倒,就会导致死锁。

从无锁到互斥同步锁(Synchronized和ReentrantLock),然后就是ReadWriteLock接口下的ReentrantReadWriteLock,他们从安全性和并发性考虑,无锁在多线程访问情况下,安全性是无法保证的,而独占式的互斥同步锁ReentrantLock和Synchronized,虽然对比无锁访问程序从无序到有序,数据具有一致性。 

ReentrantReadWriteLock的特性

公平性选择

支持公平锁与非公平锁的获取方式,但是比较吞吐量非公平锁还是优于公平锁。

该特性与ReentrantLock相似,在默认情况下是获取非公平锁,构造方法传入true获取公平锁。 

可重入

支持可重入,以读写线程为例,读线程在获取了读锁之后,能够再次获取读锁,写线程在获取了写锁之后能够再次获取写锁,同时也可以获取读锁(锁降级)。但是写线程不能先获取读锁,再获取写锁,这样会让线程陷入死锁。

        ReentranReadWriteLock中使用一个int state变量来维护读锁和写锁的状态。int类型为4字节32位,用state的高16位来存储读锁的状态,用低16位来存储写锁的状态。主要是为了实现可重入,因为读锁使用高16位来记录,因此每次获取读锁成功都需要+1,再向左移动16位。

锁降级

锁降级的流程:

            获取写锁--->获取读锁--->释放写锁--->释放读锁

重入还允许通过获取写入锁定,然后读取锁,再释放写锁,从写锁到读取锁,但是从读锁升级到写锁是不可能的,其实可以参考文件权限,写文件的权限是大于读文件的权限,这样的锁降级的设计其实是为了写完可以马上读,防止其他线程对数据进行修改,目的是为了保证数据的可见性,其实是变为了悲观锁。

Oracle公司在ReentrantReadWriteLock底层源码中有一个缓存数据类,volatile 修饰的cacheValid变量,保证了数据的可见性,在先获取读锁时,如果cache是不可用的,那么就释放读锁,获取写锁,修改数据之前,要先检查cacheValid,然后修改数据,将cacheValid为true,在释放写锁前抢占读锁,此时cache中的数据可以使用,释放写锁,释放读锁。

StampedLock(邮戳锁)

StampedLock解决了ReentrantReadWriteLock可能会产生写锁饥饿问题,StampedLock是一个乐观锁,stamp是戳记的意思,代表了锁的状态,当stamp返回0时,表示线程获取锁失败,当释放锁/转换锁时,都要传入最初获取的stamp值。并且StampLock是不可重入的。

 获取锁时返回一个邮戳,stamp为0失败,其余为成功。

释放锁时,需要一个邮戳,stamp必须是和成功获取锁时得到的stamp一致。

访问模式描述
Reading(读模式)与ReentrantReadWriteLock读锁类似
Writing(写模式)与ReentrantReadWriteLock写锁类似
Optimistic Reading(乐观读模式)无锁机制,支持读写并发,假如检查到邮戳被修改,那么升级为悲观锁再读一次。

乐观读中有写操作插入,如果戳记没有被修改,就依旧是乐观锁,但戳记被修改,与初始的戳记对比不相同,就返回false,需要将乐观读变为悲观读,也就是需要读写互斥,得到新的修改值。

StampedLock缺点

  • 不可以重入(从一个锁到另一个锁)
  • StampedLock的悲观读锁和写锁都不支持条件变量(Condition)
  • 使用StampedLock不要调用中断操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值