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

本文详细解析了Java并发包juc中AQS实现的公平锁与非公平锁的主要区别。非公平锁允许未入队列的线程与队列头部线程竞争锁,而公平锁则增加了对当前线程是否为队列头结点的检查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

 

1.1 NonfairSync.lock() 

Java代码  收藏代码
  1. final void lock() {  
  2.     if (compareAndSetState(01))//没有进入等待队列,也可以获取锁  
  3.         setExclusiveOwnerThread(Thread.currentThread());  
  4.     else  
  5.         acquire(1);  
  6. }  

 

2.1 FairSync.lock()

Java代码  收藏代码
  1. final void lock() {  
  2.         acquire(1);  
  3. }  

 

2.2 FairSync.tryAcquire()

Java代码  收藏代码
  1. /** 
  2.          * Fair version of tryAcquire.  Don't grant access unless 
  3.          * recursive call or no waiters or is first. 
  4.          */  
  5.         protected final boolean tryAcquire(int acquires) {  
  6.             final Thread current = Thread.currentThread();  
  7.             int c = getState();  
  8.             if (c == 0) {  
  9.                 if (isFirst(current) &&//只有等待队列为空或当前线程是队列头结点才可以获取锁  
  10.                     compareAndSetState(0, acquires)) {  
  11.                     setExclusiveOwnerThread(current);  
  12.                     return true;  
  13.                 }  
  14.             }  
  15.             else if (current == getExclusiveOwnerThread()) {  
  16.                 int nextc = c + acquires;  
  17.                 if (nextc < 0)  
  18.                     throw new Error("Maximum lock count exceeded");  
  19.                 setState(nextc);  
  20.                 return true;  
  21.             }  
  22.             return false;  
  23.         }  

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

 

2.3 AbstractQueuedSynchronizer.isFirst()

Java代码  收藏代码
  1. /** 
  2.      * Return {@code true} if the queue is empty or if the given thread 
  3.      * is at the head of the queue. This is reliable only if 
  4.      * <tt>current</tt> is actually Thread.currentThread() of caller. 
  5.      */  
  6.     final boolean isFirst(Thread current) {  
  7.         Node h, s;  
  8.         return ((h = head) == null ||  
  9.                 ((s = h.next) != null && s.thread == current) ||  
  10.                 fullIsFirst(current));  
  11.     }  

 

2.4 AbstractQueuedSynchronizer.fullIsFirst()

Java代码  收藏代码
  1. final boolean fullIsFirst(Thread current) {  
  2.         // same idea as fullGetFirstQueuedThread  
  3.         Node h, s;  
  4.         Thread firstThread = null;  
  5.         if (((h = head) != null && (s = h.next) != null &&  
  6.              s.prev == head && (firstThread = s.thread) != null))  
  7.             return firstThread == current;  
  8.         Node t = tail;  
  9.         while (t != null && t != head) {  
  10.             Thread tt = t.thread;  
  11.             if (tt != null)  
  12.                 firstThread = tt;  
  13.             t = t.prev;  
  14.         }  
  15.         return firstThread == current || firstThread == null;  
  16.     }  
 

总结:

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

1.等待队列为空。

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

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


原文http://suo.iteye.com/blog/1330485

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值