ReentrantLock核心原理!
发表于更新于
ReentrantLock是可重入的互斥锁。
ReentrantLock底层基于AbstractQueuedSynchronizer实现。
整体结构
ReentrantLock内部定义了专门的组件Sync,Sync继承AbstractQueuedSynchronizer提供释放资源的实现。
NonfairSync和FairSync是基于Sync扩展的子类,即ReentrantLock的非公平模式与公平模式。
它们作为Lock接口功能的基本实现。

在ReentrantLock中,它对AbstractQueuedSynchronizer的state状态值定义为线程获取该锁的重入次数。
state状态值为0表示当前没有被任何线程持有,state状态值为1表示被其他线程持有。
因为支持可重入,如果是持有锁的线程,再次获取同一把锁,直接成功,并且state状态值+1,线程释放锁state状态值-1。
同理重入多次锁的线程,需要释放相应的次数。
Sync
Sync继承了AbstractQueuedSynchronizer,是ReentrantLock的核心,NonfairSync与FairSync都是基于Sync扩展出来的子类。
Sync实现了AQS类的释放资源(tryRelease),然后抽象了一个获取锁的函数(lock)让子类自行实现。
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
| 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; } }
|
tryRelease流程:

NonfairSync
在ReentrantLock中支持两种获取锁的策略,分别是非公平策略与公平策略,NonfairSync就是非公平策略。
NonfairSync继承Sync实现了lock函数,CAS设置状态值state为1代表获取锁成功。
否则执行AQS的acquire函数(获取锁模板)。
另外NonfairSync还实现了AQS留给子类实现的tryAcquire函数(获取资源)。
直接使用Sync提供的nonfairTryAcquire函数来实现tryAcquire。
最后子类实现的tryAcquire函数在AQS的acquire函数中被使用。
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
| 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); } }
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
|
当前线程查看资源是否可获取:
可获取,尝试使用CAS设置state为1,CAS成功代表获取资源成功,否则获取资源失败。
不可获取,判断当线程是不是持有锁的线程,如果是,state重入计数,获取资源成功,否则获取资源失败。

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
|
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; }
|
FairSync
FairSync流程与NonfairSync基本一致,唯一的区别就是在CAS执行前,多了一步hasQueuedPredecessors函数,这一步就是判断当前线程是不是CLH队列被唤醒的线程,如果是就执行CAS,否则获取资源失败。

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
| 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; } }
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
|
Lock的实现
1 2 3 4 5 6 7 8 9 10 11 12
| private final Sync sync;
public ReentrantLock() { sync = new NonfairSync(); }
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
|
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
| public class ReentrantLock implements Lock, java.io.Serializable { private static final long serialVersionUID = 7373984872572414699L; private final Sync sync;
public ReentrantLock() { sync = new NonfairSync(); }
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
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(); }
}
|