并发包独占锁ReentrantLock与读写锁ReentrantReadWriteLock
Posted wqff-biubiu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发包独占锁ReentrantLock与读写锁ReentrantReadWriteLock相关的知识,希望对你有一定的参考价值。
两个锁都是依赖AQS实现的,方法基本是Sync的封装,主要看Sync的设计实现,
一、可重入独占锁ReentrantLock
1.静态内部抽象类Sync
//继承AQS abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; /** * 延迟到子类实现(公平锁与非公平锁) */ abstract void lock(); /** * 尝试获取非公平锁 */ final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { //计数器state == 0:锁未被持有,计数器原子性自增并设置当前线程为持有者 if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { //计数器state != 0:锁被当前线程为持有者,计数器state增加(可重入锁) int nextc = c + acquires; if (nextc < 0) // 可重入次数溢出跑错 throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) //当前线程不是锁的持有者抛出异常 throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { //计数器state == 0:释放锁,设置持有者为null free = true; setExclusiveOwnerThread(null); } setState(c); return free; } protected final boolean isHeldExclusively() { //判断当前线程是否为锁的持有者 return getExclusiveOwnerThread() == Thread.currentThread(); } final ConditionObject newCondition() { //创建条件变量 return new ConditionObject(); } // Methods relayed from outer class final Thread getOwner() { //获取当前锁的持有线程 return getState() == 0 ? null : getExclusiveOwnerThread(); } final int getHoldCount() { //当前线程为锁的持有者返回计数器state值,不是锁的持有者返回0 return isHeldExclusively() ? getState() : 0; } final boolean isLocked() { //锁是否被持有 return getState() != 0; } /** * 创建反序列化实例,重置计数器值,锁状态初始化 */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); // reset to unlocked state } }
继承Sync的非公平锁NonfairSync与公平锁FairSync
/** * 非公平锁 */ static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { if (compareAndSetState(0, 1)) //当前计数器state == 0即锁未被持有时,state自增且直接设置当前线程为锁持有者(未检查阻塞队列,破坏FIFO) setExclusiveOwnerThread(Thread.currentThread()); else //当前计数器state != 0即锁被持有时,调用AQS的独占模式获取资源,会调用下面的tryAcquire尝试获取锁 acquire(1); } //acquire方法中tryAcquire实现,尝试获取锁,若锁未被持有,直接获取锁,不入阻塞队列,破坏FIFO protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } /** * 公平锁 */ static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; final void lock() { acquire(1); } /** * 公平锁尝试获取资源,锁未被持有时,先队列,后当前线程 */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { //计数器state == 0,锁未被持有 if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { //AQS阻塞队列为空或者当前线程是阻塞队列头结点的后继节点,直接设置当前线程为锁的持有者,计数器state自增 setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { //计数器state != 0.锁被持有且持有者是当前线程,计数器state自增 int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } }
2.ReentrantLock的变量与构造方法
private final Sync sync;//实际的锁对象 public ReentrantLock() { sync = new NonfairSync();//无参构造函数默认非公平锁 == ReentrantLock(false) } public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync();//可指定公平锁还是非公平锁 }
3.ReentrantLock的方法:都是Sync的封装
//尝试获取锁 public void lock() { sync.lock(); } //尝试获取锁,不忽略中断,中断抛错 public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } //尝试获取锁 public boolean tryLock() { return sync.nonfairTryAcquire(1); } //尝试一定时间内获取锁 public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } //释放锁 public void unlock() { sync.release(1); } //创建条件变量 public Condition newCondition() { return sync.newCondition(); } //返回锁的重入数,不是锁持有者则返回0 public int getHoldCount() { return sync.getHoldCount(); } //判断当前线程是否为锁的持有者 public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } //判断锁是否被持有 public boolean isLocked() { return sync.isLocked(); } //判断是否公平锁 public final boolean isFair() { return sync instanceof FairSync; } //获取锁的持有者 protected Thread getOwner() { return sync.getOwner(); } //判断AQS队列是否为空 public final boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } // public final boolean hasQueuedThread(Thread thread) { return sync.isQueued(thread); } public final int getQueueLength() { return sync.getQueueLength(); } protected Collection<Thread> getQueuedThreads() { return sync.getQueuedThreads(); } public boolean hasWaiters(Condition condition) { if (condition == null) throw new NullPointerException(); if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner"); return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition); } public int getWaitQueueLength(Condition condition) { if (condition == null) throw new NullPointerException(); if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner"); return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition); } protected Collection<Thread> getWaitingThreads(Condition condition) { if (condition == null) throw new NullPointerException(); if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner"); return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition); }
以上是关于并发包独占锁ReentrantLock与读写锁ReentrantReadWriteLock的主要内容,如果未能解决你的问题,请参考以下文章
Java 并发编程 进阶 -- Java并发包中锁原理剖析(LockSupport抽象同步队列AQS独占锁ReentrantLock读写锁ReentrantReadWriteLock)
Java中juc并发包下的Condition接口与ReentrantLock对象锁实现线程通信