欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

ReentrantReadWriteLock

最编程 2024-07-28 19:27:25
...
的实现ReadWriteLock支持类似的语义ReentrantLock

该类具有以下属性:

  • 收购订单

    此类不会强制执行锁定访问的读取器或编写器首选项顺序。 但是,它确实支持可选的公平政策。

    非公平模式(默认)
    当构造为非公平(默认)时,读取和写入锁定的输入顺序是未指定的,受重入约束的限制。 持续争用的非公平锁定可能无限期地推迟一个或多个读取器或写入器线程,但通常具有比公平锁定更高的吞吐量。
    公平模式
    当构造为公平时,线程使用近似到达顺序策略争用进入。 当释放当前保持的锁定时,将为最长等待的单个写入器线程分配写入锁定,或者如果有一组读取器线程等待的时间长于所有等待的写入器线程,则将为该组分配读取锁定。

    尝试获取公平读锁定(非重复)的线程将阻止是否保持写锁定,或者存在等待写入器线程。 在最旧的当前等待的写入器线程获取并释放写锁定之前,线程将不会获取读锁定。 当然,如果等待的写入者放弃其等待,将一个或多个读取器线程作为队列中最长的服务器并且写锁定空闲,那么将为这些读取器分配读锁定。

    尝试获取公平写锁定(非重复)的线程将阻塞,除非读取锁定和写入锁定都是空闲的(这意味着没有等待的线程)。 (请注意,非阻塞ReentrantReadWriteLock.ReadLock.tryLock()ReentrantReadWriteLock.WriteLock.tryLock()方法不遵循此公平设置,并且如果可能,将立即获取锁定,无论等待线程如何。)

  • 重入

    此锁允许读取器和写入器以ReentrantLock的样式重新获取读或写锁。 在写入线程持有的所有写锁定都被释放之前,不允许使用非重入读取器。

    此外,编写器可以获取读锁定,但反之亦然。 在其他应用程序中,在调用期间保持写入锁定或在对读取锁定执行读取的方法的回调时,重入可能很有用。 如果读者试图获取写锁定,它将永远不会成功。

  • 锁定降级

    Reentrancy还允许通过获取写锁定,然后读取锁定然后释放写入锁定,从写入锁定降级到读取锁定。 然而,从读锁定写锁定升级是不可能的。

  • 锁定获取中断

    读取锁定和写入锁定都支持锁定获取期间的中断。

  • Condition支持

    写锁定提供Condition实现,相对于写锁定,其行为方式相同,因为ReentrantLock.newCondition()提供的Condition实现针对ReentrantLock 当然,这个Condition只能与写锁一起使用。

    读锁定不支持ConditionreadLock().newCondition()抛出UnsupportedOperationException

  • 仪表

    此类支持确定锁是保持还是争用的方法。 这些方法用于监视系统状态,而不是用于同步控制。

此类的序列化与内置锁的行为方式相同:反序列化锁处于解锁状态,无论序列化时的状态如何。

示例用法 下面是一个代码草图,展示了如何在更新缓存后执行锁定降级(在以非嵌套方式处理多个锁时,异常处理尤其棘手):

   class CachedData { Object data; boolean cacheValid; final 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(); try { // 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(); } finally { rwl.writeLock().unlock(); // Unlock write, still hold read } } try { use(data); } finally { rwl.readLock().unlock(); } } } 
ReentrantReadWriteLocks可用于在某些类型的集合的某些用途中提高并发性。 这通常是值得的,只有当预期集合很大时,由读取器线程比读写器线程访问更多,并且需要具有超过同步开销的开销的操作。 例如,这是一个使用TreeMap的类,该类预计很大并且可以同时访问。
   class RWDictionary { private final Map<String, Data> m = new TreeMap<>(); private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock r = rwl.readLock(); private final Lock w = rwl.writeLock(); public Data get(String key) { r.lock(); try { return m.get(key); } finally { r.unlock(); } } public List<String> allKeys() { r.lock(); try { return new ArrayList<>(m.keySet()); } finally { r.unlock(); } } public Data put(String key, Data value) { w.lock(); try { return m.put(key, value); } finally { w.unlock(); } } public void clear() { w.lock(); try { m.clear(); } finally { w.unlock(); } } } 

实施说明

此锁最多支持65535个递归写锁和65535个读锁。 尝试超过这些限制会导致锁定方法引发Error次抛出。