您的位置:首页 > 其它

ReentrantReadWriteLock 可重入读写锁的理解

2012-11-01 10:39 561 查看
  多线程读取并修必一个资源时,我们过去通常使用synchronized同步锁,这个是有性能损失的,很多情况下:资源对象总是被大量并发读取,偶尔有一个线程进行修改,也就是说:以读为主,修改不是很频繁,那么我们在JDK5中用ReentrantReadWriteLock就获得比synchronized更高并发性能,高并发性能是我们使用JDK5的主要目的,而不是annotaion和泛型等设计优点。

  在使用ReentrantReadWriteLock 时应明确以下几点:

(1)在代码中添加读锁(lock.readLock().lock() ) 的目的:如果有一线程在读取数据时,此时恰好有另一线程,正以写锁的方式在修改该数据,此时读取数据的线程如果加了读锁,将被阻塞,直到另一线程的写锁被释放才能继续读,而如果读取数据的线程未加读锁,那么它的读将不被阻塞,就有可能读入被修改前的数据。总结:读锁离开了写锁就没有了意义

  (2)重入:此锁允许 reader 和 writer 按照 ReentrantLoc 的样式重新获取读取锁或写入锁。在写入线程保持的所有写入锁都已经释放后,才允许重入 reader 使用它们。此外,writer 可以获取读取锁,但反过来则不成立。在其他应用程序中,当在调用或回调那些在读取锁状态下执行读取操作的方法期间保持写入锁时,重入很有用。如果 reader 试图获取写入锁,那么将永远不会获得成功。

(3)锁降级:重入还允许从写入锁降级为读取锁,其实现方式是:先获取写入锁,然后获取读取锁,最后释放写入锁。但是,从读取锁升级到写入锁是不可能的

下面是JDK的一个例子,展示了如何利用重入来执行升级缓存后的锁降级(为简单起见,省略了异常处理):

class CachedData {
Object data;
volatile boolean cacheValid;
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) {
// Must release read lock before acquiring write lock
rwl.readLock().unlock();
rwl.writeLock().lock();
// Recheck state because another thread might have acquired
//   write lock and changed state before we did.
if (!cacheValid) {
data = ...
cacheValid = true;
}
// Downgrade by acquiring read lock before releasing write lock
rwl.readLock().lock();
rwl.writeLock().unlock(); // Unlock write, still hold read
}

use(data);
rwl.readLock().unlock();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: