公平锁
上锁
acquire
上锁过程lock()
->acquire(1)
acquire方法会tryAcquire
尝试获取锁,获取不到开始入队。是否公平就体现在tryAcquire
方法中。
public final void acquire(int arg) {
//尝试获取锁,获取不到开始入队
if (!tryAcquire(arg) &&
//addWaiter构造队列,入队
//acquireQueued循环抢占及休眠
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
tryAcquire
判断
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//锁未占用
if (c == 0) {
//判断是否有前置等待线程
//无前置等待线程 or 等待线程就是自己才可以抢占
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;
}
hasQueuedPredecessors
public final boolean hasQueuedPredecessors() {
Node t = tail;
Node h = head;
Node s;
return h != t && //队列有内容
((s = h.next) == null ||
s.thread != Thread.currentThread()); //队列第一个等待线程非自己
}
后面为addWaiter
和acquireQueued
常规过程。代码就不分析了。
解锁
unlock
sync.release
- tryRelease释放锁,返回是否完全释放
- 完全释放后,unpark头结点的线程
public final boolean release(int arg) {
//tryRelease返回锁是否完全释放
if (tryRelease(arg)) {
Node h = head;
//正常不会是0,因为在acquireQueued过程已经设置为SIGNAL
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
unparkSuccessor
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
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);
}
非公平锁
上锁
lock
直接尝试抢占
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
acquire
代码和公平锁一致,只是抢占tryAcquire
有些区别,就是暴力抢占,不判断第一个等待线程。
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;
}
网友评论