ReentrantReadWriteLock源码浅析

您所在的位置:网站首页 reentrantreadwritelock应用场景 ReentrantReadWriteLock源码浅析

ReentrantReadWriteLock源码浅析

#ReentrantReadWriteLock源码浅析| 来源: 网络整理| 查看: 265

ReentrantReadWriteLock简介

ReentrantReadWriteLock是读写锁。一般的排他性锁在一个线程执行某个方法获得到锁之后(暂未释放锁),其他线程再想执行同一方法便会阻塞,即使该方法执行的是读操作。而在很多场景下,读多写少,这时如果继续使用排他锁,性能便会大受影响。读写锁的出现正是为了解决此类问题,读写锁内部有读锁和写锁,读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的。读锁和写锁分离从而读写分离提升性能,其主要应用于读多写少的场景。下面来看看ReentrantReadWriteLock的使用示例

public class ReadWriteLockSample { private Map map = new HashMap(); private ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private Lock readLock = readWriteLock.readLock(); private Lock writeLock = readWriteLock.writeLock(); public Object get(String key){ readLock.lock(); try { try { Thread.sleep(new Random().nextInt(3000)); } catch (InterruptedException e) { e.printStackTrace(); } return map.get(key); }finally { readLock.unlock(); System.out.println(Thread.currentThread().getName()+"读操作执行完毕"); } } public void put(String key, Object value){ writeLock.lock(); try { try { Thread.sleep(new Random().nextInt(3000)); } catch (InterruptedException e) { e.printStackTrace(); } map.put(key,value); }finally { writeLock.unlock(); System.out.println(Thread.currentThread().getName()+"写操作执行完毕"); } } public static void main(String[] args) { final ReadWriteLockSample rwl = new ReadWriteLockSample(); rwl.put("key1", "value1"); new Thread(new Runnable() { @Override public void run() { rwl.put("key1", "value1"); } }).start(); new Thread(new Runnable() { @Override public void run() { System.out.println(rwl.get("key1")); } }).start(); } }

读写锁允许同时执行多个读操作,但同一时间只能有一个线程在执行写操作。

ReentrantReadWriteLock实现原理

ReentrantReadWriteLock内部维护一把读锁和写锁,读锁和写锁都是通过定义在其内部的AQS子类Sync来实现。和ReentrantLock一样,读锁和写锁也支持公平锁和非公平锁,默认创建的都是非公平锁。

public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable { /** 读锁,ReadLock是自定义AQS的子类 */ private final ReentrantReadWriteLock.ReadLock readerLock; /** 写锁,WriteLock是自定义AQS的子类*/ private final ReentrantReadWriteLock.WriteLock writerLock; /** 自定义AQS的子类 */ final Sync sync; ...... } 读写状态

我们知道在AQS内部有个volatile修饰的int变量state来表示同步状态,在读写锁内部也使用了一个int类型的变量state来标识多个读锁和一个写锁的状态。如何用一个int变量来标识呢?ReentrantReadWriteLock中将32位的int值分成两段,高16位用来标识读,低16位用来标识写。示意图如下

读写锁中的state变量 低16位的写状态之所以会大于1,是因为写锁是可重入的,它表示的是写锁重入的次数,而不是当前写锁的个数。 基于这种设计,读锁和写锁的状态获取和设置如下

读锁状态的获取:state>>16 读锁状态的写入:state+(1


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3