关于reentrantLock 中 fair 和 unfair体现
对于 reentrantLock 其核心实际是利用AbstractQueueSynchronizer (AQS);
对于reentrant就是通过判断当前线程是否相等作为可重入条件
AQS 实际就是一个双向链表组成的队列,对于队列中存在的节点实际就是等待获取锁的线程;
对于AQS一般是设置在有效时间内获取到锁,当获取锁失败的情况下才会被添加到队列中,对于队列中的等待者实际就是通过循环一直尝试获取锁,当在尝试获取锁失败的情况下且未达到获取锁等待时间时,会尝试将当前线程(这里主要是针对的当前执行循环的线程)挂起,当在释放锁的情况下,会通知当前被挂起的线程,重新执行获取锁的过程; 直到获取锁成功或等待获取锁超时或竞争锁的线程消亡,节点才会被移除掉;
对于AQS实际队列的形式满足先进先出(FIFO)的特点;
对于reentrantLock 中的 fair 和 unfair 其主要体现在 当同时存在 未保存到队列中的竞争者 和 队列中排队等候的竞争者 在上一个线程释放锁之后,其获取锁的顺序优先级
public final boolean hasQueuedPredecessors() { // The correctness of this depends on head being initialized // before tail and on head.next being accurate if the current // thread is first in queue. Node t = tail; // Read fields in reverse initialization order Node h = head; Node s; return h != t && // 首先判断队列中是否存在数据,当 h!=t时说明队列中存在数据 // 当队列中存在数据时,判断当前head节点是否已出队,当s==null说明已出队 // 当s!=null时,需要判断s节点的线程是否是当前线程, //当其等于当前线程时,说明队列中下一个等待者就是当前线程 ((s = h.next) == null || s.thread != Thread.currentThread()); }
protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && // 首先判断队列中是否存在数据,以及存在的数据下一个等待者是否就是本身 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; }
对于fair 中 hasQueuedPredecessors中出现的判断情况
因此对于fair 锁释放(state 为 0)情况下,非队列中的竞争者能直接进行尝试加锁的情况就只有以下两种情况
除以上两种情况外其余情况都会直接追加到AQS等待队列中
简单总结一下,对于fair主要是针对AQS队列中元素的公平
java学习-reentrantlock-fair和unfair
原文:https://www.cnblogs.com/xingguoblog/p/14189289.html