您的位置:首页 > 产品设计 > UI/UE

java并发编程--AbstractQueuedSynchronizer公平锁和非公平锁分析(三)

2015-08-13 11:31 796 查看
juc包中,aqs实现的公平锁和非公平锁的最主要的区别是:非公平锁中,那些尝试获取锁且尚未进入等待队列的线程会和等待队列head结点的线程发生竞争。公平锁中,在获取锁时,增加了isFirst(current)判断,当且仅当,等待队列为空或当前线程是等待队列的头结点时,才可尝试获取锁。

1.1 NonfairSync.lock()

Java代码


final void lock() {

if (compareAndSetState(0, 1))//没有进入等待队列,也可以获取锁

setExclusiveOwnerThread(Thread.currentThread());

else

acquire(1);

}

2.1 FairSync.lock()

Java代码


final void lock() {

acquire(1);

}

2.2 FairSync.tryAcquire()

Java代码


/**

* Fair version of tryAcquire. Don't grant access unless

* recursive call or no waiters or is first.

*/

protected final boolean tryAcquire(int acquires) {

final Thread current = Thread.currentThread();

int c = getState();

if (c == 0) {

if (isFirst(current) &&//只有等待队列为空或当前线程是队列头结点才可以获取锁

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;

}

关于当前线程是否是队列头结点的判断,详见下面两个函数:

2.3 AbstractQueuedSynchronizer.isFirst()

Java代码


/**

* Return {@code true} if the queue is empty or if the given thread

* is at the head of the queue. This is reliable only if

* <tt>current</tt> is actually Thread.currentThread() of caller.

*/

final boolean isFirst(Thread current) {

Node h, s;

return ((h = head) == null ||

((s = h.next) != null && s.thread == current) ||

fullIsFirst(current));

}

2.4 AbstractQueuedSynchronizer.fullIsFirst()

Java代码


final boolean fullIsFirst(Thread current) {

// same idea as fullGetFirstQueuedThread

Node h, s;

Thread firstThread = null;

if (((h = head) != null && (s = h.next) != null &&

s.prev == head && (firstThread = s.thread) != null))

return firstThread == current;

Node t = tail;

while (t != null && t != head) {

Thread tt = t.thread;

if (tt != null)

firstThread = tt;

t = t.prev;

}

return firstThread == current || firstThread == null;

}

总结:

线程为首结点成立的情况:

1.等待队列为空。

2.等待队列head的next结点的thread为当前线程(head.next.thread = currentThread),即线程为等待队列除哑结点外的第一个结点。

3.等待队列head结点到某个结点(暂命名为结点s),之间的所有结点的thread变量为null,且结点s的thread为当前线程。

原文http://suo.iteye.com/blog/1330485
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: