juc包中,aqs实现的公平锁和非公平锁的最主要的区别是:非公平锁中,那些尝试获取锁且尚未进入等待队列的线程会和等待队列head结点的线程发生竞争。公平锁中,在获取锁时,增加了isFirst(current)判断,当且仅当,等待队列为空或当前线程是等待队列的头结点时,才可尝试获取锁。
1.1 NonfairSync.lock()
- final void lock() {
- if (compareAndSetState(0, 1))//没有进入等待队列,也可以获取锁
- setExclusiveOwnerThread(Thread.currentThread());
- else
- acquire(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为当前线程。
原文http://suo.iteye.com/blog/1330485