java并发编程--AbstractQueuedSynchronizer公平锁和非公平锁分析(三)
juc包中,aqs实现的公平锁和非公平锁的最主要的区别是:非公平锁中,那些尝试获取锁且尚未进入等待队列的线程会和等待队列head结点的线程发生竞争。公平锁中,在获取锁时,增加了isFirst(current)判断,当且仅当,等待队列为空或当前线程是等待队列的头结点时,才可尝试获取锁。
?
?
1.1 NonfairSync.lock()?
final void lock() {if (compareAndSetState(0, 1))//没有进入等待队列,也可以获取锁setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}?
2.1 FairSync.lock()
final void lock() { acquire(1);}?
2.2 FairSync.tryAcquire()
/** * 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()
/** * 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()
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为当前线程。
?