`
wode66
  • 浏览: 738695 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

阅读更多

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为当前线程。

 

分享到:
评论
1 楼 nmgrd 2017-04-23  
赞一个,在分析AQS源码的博客当中,楼主是写的最细致,最易懂,最走心的,本人评论时间是20170423,截止目前,本人还没发现其他更好的AQS源码分析

相关推荐

Global site tag (gtag.js) - Google Analytics