ReentrantLock源码分析 介绍 我们在上一篇已经分析了AbstractQueuedSynchronier的源码,接下来就分析ReentrantLock的源码
内部类分析 ReentrantLock内部总共有三个内部类,并且FairSync和NonfairSync都是Sync的具体实现
Sync 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 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 ) { if (compareAndSetState(0 , acquires)) { setExclusiveOwnerThread(current); return true ; } } else if (current == getExclusiveOwnerThread()) { 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 ) { free = true ; setExclusiveOwnerThread(null ); } setState(c); return free; } protected final boolean isHeldExclusively () { return getExclusiveOwnerThread() == Thread.currentThread(); } final ConditionObject newCondition () { return new ConditionObject(); } final Thread getOwner () { return getState() == 0 ? null : getExclusiveOwnerThread(); } final int getHoldCount () { 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 ); } }
Sync是抽象同步器,它继承了AQS,实现了部分非公平和公平的方法,后续的FairSync和NonfairSync都继承Sync并实现了lock和tryAcquire方法
FairSync 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 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 ) { if (!hasQueuedPredecessors() && compareAndSetState(0 , acquires)) { setExclusiveOwnerThread(current); return true ; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0 ) throw new Error("Maximum lock count exceeded" ); setState(nextc); return true ; } return false ; } }
NonFairSync 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L ; final void lock () { if (compareAndSetState(0 , 1 )) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1 ); } protected final boolean tryAcquire (int acquires) { return nonfairTryAcquire(acquires); } }
由上可知:公平锁和非公平锁在获取资源时的唯一区别是:公平锁会使用hasQueuedPredecessors方法去判断当前线程节点是否为CLH队列的第一个,如果是第一个才会往下获取,否则false
构造函数 1 2 3 4 5 6 7 8 9 10 11 12 13 public ReentrantLock () { sync = new NonfairSync(); } public ReentrantLock (boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
ReentrantLock使用示例(示例来自于源码) 1 2 3 4 5 6 7 8 9 10 11 12 13 class X { ReentrantLock lock = new ReentrantLock(); public void m () { assert lock.getHoldCount() == 0 ; lock.lock(); try { } finally { lock.unlock(); } } }
上述为ReentrantLock的最基本用法,主要使用到的是ReentrantLock的lock方法和unlock方法,下面我们就主要解析这两个方法:
lock 1 2 3 public void lock () { sync.lock(); }
即内部是调用了同步类sync的方法,再去看sync的lock方法:发现其是抽象方法,具体实现由FairSync公平同步器和NonfairSync非公平同步器 FairSync的lock:
1 2 3 final void lock () { acquire(1 ); }
NonfairSync的lock:
1 2 3 4 5 6 final void lock () { if (compareAndSetState(0 , 1 )) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1 ); }
由上可知:公平锁与非公平锁在lock的时候的区别是:compareAndSetState可以将资源状态由0设置为1,即将资源占有线程设置为当前线程,而公平锁不会这样,它会acquire从CLH队列中获取第一个 acquire方法则是AQS类中的方法,已经在上一篇AQS中解析了,具体可以看上一篇 lock流程图如下:
unlock 1 2 3 public void unlock () { sync.release(1 ); }
内部还是调用了同步类的release方法,在这里是直接使用了AQS的release方法
1 2 3 4 5 6 7 8 9 10 11 12 13 public final boolean release (int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0 ) unparkSuccessor(h); return true ; } return false ; }
tryRelease方法则是Sync来实现的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 protected final boolean tryRelease (int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false ; if (c == 0 ) { free = true ; setExclusiveOwnerThread(null ); } setState(c); return free; }
unlock流程图如下:
示例分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public class MyThread extends Thread { private Lock lock; public MyThread (String name, Lock lock) { super (name); this .lock = lock; } @Override public void run () { lock.lock(); try { System.out.println(Thread.currentThread() + " running" ); Thread.sleep(500 ); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } public class ReentrantLockDemo { public static void main (String[] args) { Lock lock = new ReentrantLock(true ); MyThread t1 = new MyThread("t1" , lock); MyThread t2 = new MyThread("t2" , lock); MyThread t3 = new MyThread("t3" , lock); t1.start(); t2.start(); t3.start(); } }