JDK7中ReadWriteLock源码概述

来源:互联网 发布:tableview卡顿优化 编辑:程序博客网 时间:2024/06/15 05:46
ReadWriteLock是java.util.concurrent.locks下的接口, 所有已知实现类:ReentrantReadWriteLock

ReadWriteLock维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。只要没有writer,读取锁可以由多个reader线程同时保持。写入锁是独占的。

所有ReadWriteLock实现都必须保证writeLock操作的内存同步效果也要保持与相关readLock的联系。也就是说成功获取读锁的线程会看到写入锁之前版本所做的所有更新。

与互斥锁相比,读-写锁允许对共享数据进行更高级别的并发访问。虽然一次只有一个线程(writer线程)可以修改共享数据,但在许多情况下,任何数量的线程可以同时读取共享数据(reader线程),读-写锁利用了这一点。从理论上讲,与互斥锁相比,使用读-写锁所允许的并发性增强将带来更大的性能提高。在实践中只有在多处理器上并且只在访问模式适用于共享数据时,才能完全实现并发性增强。

与互斥锁相比,使用读-写锁能否提升性能则取决于读写操作期间读取数据相对于修改数据的频率,以及数据的争用,即在同一时间试图对该数据执行读取或写入操作的线程数。例如某个最初用数据填充并且之后不经常对其进行修改的collection,因为经常对其进行搜索(比如搜索某种目录),所以这样的collection是使用读-写锁的理想候选者。但是如果数据更新变得频繁,数据在大部分时间都被独占锁,这时就算存在并发性增强也是微不足道的。更进一步地说,如果读取操作所用时间太短,则读-写锁实现(它本身就比互斥锁复杂)的开销将成为主要的执行成本,在许多读-写锁实现仍然通过一小段代码将所有线程序列化时更是如此。最终只有通过分析和测量,才能确定应用程序是否适合使用读-写锁。

尽管读-写锁的基本操作是直截了当的,但实现仍然必须作出许多决策,这些决策可能会影响给定应用程序中读-写锁的效果。这些策略的例子包括:在writer释放写入锁时,reader和writer都处于等待状态,在这时要确定是授予读取锁还是授予写入锁。Writer优先比较普遍,因为预期写入所需的时间较短并且不那么频繁。Reader优先不太普遍,因为如果reader正如预期的那样频繁和持久,那么它将导致对于写入操作来说较长的时延。公平或者“按次序”实现也是有可能的。在reader处于活动状态而writer处于等待状态时,确定是否向请求读取锁的reader授予读取锁。Reader优先会无限期地延迟writer,而writer优先会减少可能的并发。


确定是否重新进入锁:

可以使用带有写入锁的线程重新获取它吗?

可以在保持写入锁的同时获取读取锁吗?

可以重新进入写入锁本身吗?

可以将写入锁在不允许其它writer干涉的情况下降级为读取锁吗?

可以优先于其它等待的reader或writer将读取锁升级为写入锁吗?

当评估给定实现是否适合您的应用程序时,应该考虑所有这些情况。

ReadWriteLock提供的方法不多,具体说明如下:
Lock readLock()
返回用于读取操作的锁。

Lock writeLock()
返回用于写入操作的锁。
原创粉丝点击