总览
- ReentrantLock implements Lodk
- ReentrantLock 只有一个成员变量:
private final Sync sync - Sync extends AbstractQueuedSynchronizer
- Sync 有两个实现类NonfairSync,FairSync 且只有lock(),tryAcquire(int arg)两个函数有不同实现
对比NonfairSync,FairSync
lock()
NonfairSync
final void lock() {
if (compareAndSetState(0, 1))
//第一个区别,非公平锁会先尝试获取锁
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
FairSync
final void lock() {
acquire(1);
}
acquire(int arg)
public final void acquire(int arg) {
//这里是第二个区别,tryAcquire函数 公平锁和非公平锁都有自己的实现
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
tryAcquire(int acquires)
NonfairSync
protected final boolean tryAcquire(int acquires) {
//调用父类Sync的nonfairTryAcquire(int acquires)
return nonfairTryAcquire(acquires);
}
Sync
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) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
FairSync
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()) {
//如果持有锁的线程是自己state+1
//可重入性
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
AbstractQueuedSynchronizer
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
//h==t || (h.next != null && h.next.thread = currentThread)
//翻译过来就是队列为空 或者 队列等待的第一个线程就是自己
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
acquireQueued(final Node node, int arg)
AbstractQueuedSynchronizer
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
AbstractQueuedSynchronizer
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
释放锁
unlock()
Sync
public void unlock() {
sync.release(1);
}
AbstractQueuedSynchronizer
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
ReentrantLock
//逻辑很简单
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;
}
AbstractQueuedSynchronizer
private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
LockSupport
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}