ReentrantReadWriteLock与ReentrantLock对比分析

来源:互联网 发布:希腊罗马神话 知乎 编辑:程序博客网 时间:2024/05/17 09:04

一.前言

ReentrantReadWriteLock与ReentrantLockde的关系并不是雷峰塔与雷锋的关系。

个人理解:
synchronized ——> ReentrantLock ——> ReentrantReadWriteLock是JVM逐渐向程序员放权的过程。

synchronized是将线程管理的操作全部交给了JVM,开发人员不需要关心线程的锁、线程切换等细节,反正在方法上或类上加上这个关键字就线程安全了。但是JVM对synchronized的实现并不高效,例如:synchronized是采用公平锁,操作会排一个队按顺序执行,来保证执行顺序。(会消耗更多的时间来排队)
而不公平情况下,是无序状态允许插队,jvm会自动计算如何处理更快速来调度插队。(如果不关心顺序,这个速度会更快)

ReentrantLock是synchronized的一个改进,他将更多的权利交给了开发人员,他允许开发人员对线程做更细粒度的操作,直接操作锁。

ReentrantReadWriteLock是ReentrantLock的进一步改进,他将锁更细分为读锁和写锁,粒度更细。

二.ReentrantReadWriteLock的使用原则

总则:ReentrantReadWriteLock分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥。如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上写锁!

(a).重入方面其内部的WriteLock可以获取ReadLock,但是反过来ReadLock想要获得WriteLock则永远都不要想。

(b).WriteLock可以降级为ReadLock,顺序是:先获得WriteLock再获得ReadLock,然后释放WriteLock,这时候线程将保持Readlock的持有。反过来ReadLock想要升级为WriteLock则不可能。

(c).ReadLock可以被多个线程持有并且在作用时排斥任何的WriteLock,而WriteLock则是完全的互斥。这一特性最为重要,因为对于高读取频率而相对较低写入的数据结构,使用此类锁同步机制则可以提高并发量。

(d).不管是ReadLock还是WriteLock都支持Interrupt,语义与ReentrantLock一致。

(e).WriteLock支持Condition并且与ReentrantLock语义一致,而ReadLock则不能使用Condition,否则抛出UnsupportedOperationException异常。

三.使用示例

 class CachedData {   Object data;   volatile 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();     }   } }
class RWDictionary {    private final Map<String, Data> m = new TreeMap<String, Data>();    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 String[] allKeys() {        r.lock();        try { return m.keySet().toArray(); }        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(); }    } }
0 0
原创粉丝点击