java.util.concurrent.locks.ReentrantLock内部维护了AbstractQueuedSynchronizer的实现类java.util.concurrent.locks.ReentrantLock.Sync,主要是基于AbstractQueuedSynchronizer实现的一些同步功能,
其中AbstractQueuedSynchronizer内部也是基于LockSupport.park(this);LockSupport.unpark(node.thread)的基本加锁解锁功能和大量的CAS 操作,实现数据的同步和线程的调度功能,为其他线程相关操作类提供了一个基础的工具类。
其中CAS操作系统调用代价低,原因如下(参考AI回答)
1. 硬件级原子指令支持
- CAS 操作通过 CPU 提供的单条原子指令(如 x86 的
cmpxchg、ARM 的ldrex/strex)直接实现比较与交换操作,无需进入内核态。 - 该指令在单个时钟周期完成内存值与预期值的比对和更新,完全在用户态执行,避免了系统调用上下文切换的开销。
2. 无锁化设计减少阻塞
- 无锁自旋:CAS 通过循环重试(自旋)处理竞争,线程始终处于运行状态,无线程挂起/唤醒操作,规避了内核调度成本。
- 对比锁机制:传统锁(如 synchronized)在竞争失败时触发线程阻塞,涉及内核态切换(如
futex系统调用)和上下文保存/恢复,开销显著高于自旋。
3. 内核交互的极简触发
- CAS 仅在发生竞争时依赖用户态指令,不强制与内核交互。
- 仅当多核 CPU 缓存不一致时,通过 MESI 协议或总线锁定协调缓存(硬件层面完成),极少触发内核介入。
4. 性能对比数据
| 场景 | CAS 机制 | synchronized | 差异来源 |
|---|---|---|---|
| 无竞争操作 | ≈10ns(用户态CAS指令) | ≈20ns(偏向锁CAS) | 67 |
| 单一竞争 | ≈100ns(自旋数次) | >1000ns(锁膨胀+内核阻塞) | 47 |
| 高并发竞争 | 自旋消耗CPU(需控制重试) | 阻塞队列调度稳定 | 412 |
java.util.concurrent.locks.ReentrantLock#lock
NonfairSync和FairSync继承Sync,分别实现了一些非公平和公平获取锁的逻辑,其中FairSync基于NonfairSync。

源码中206行可知,AQS中状态为0代表为线程占用,1代表有线程占用。所谓的锁,本质是一些数据标识。setExclusiveOwnerThread方法代表当前线程获取锁成功,设置为AQS中的独占线程。如获取锁失败,再进入209行尝试获取锁。

进入java.util.concurrent.locks.ReentrantLock.NonfairSync#tryAcquire====>java.util.concurrent.locks.ReentrantLock.Sync#nonfairTryAcquire

从131-137行可以看出新来的线程可以直接根据当前状态判断是否能拿到锁,不需要和AQS队列里的线程竞争,这就是非公平的体现。138行-144行看出如果当前线程已经是AQS中的独占线程是,再加锁时,状态会叠加,体现了可重入的特性(这段代码中当前线程是独占执行的,不需要CAS操作)。
如果nonfairTryAcquire获取失败,会先进入
java.util.concurrent.locks.AbstractQueuedSynchronizer#addWaiter

该方法主要是创建AQS双向链表中的节点,并加入链表的尾部,每个节点封装了线程对象。
进入java.util.concurrent.locks.AbstractQueuedSynchronizer#enq可以看出链表中初始以lazy的方式创建head节点
再进入java.util.concurrent.locks.AbstractQueuedSynchronizer#acquireQueued

这个方法主要是循环获取锁,如获取不到则阻塞当前线程,此时当前线程已在AQS链表中,可有其他线程(链表中前一个节点)唤醒。从862-868行看出获取锁是从链表的头部节点开始的。头部代表活跃的线程。

进入java.util.concurrent.locks.AbstractQueuedSynchronizer#shouldParkAfterFailedAcquire。可以看出,前一节点waitStatus状态必须为Node.SIGNAL,当前节点才能阻塞。因为阻塞节点的唤醒必须基于前一节点waitStatus状态。808-811行类似以lazy方式根据状态更新双向链表

java.util.concurrent.locks.ReentrantLock#unlock
java.util.concurrent.locks.ReentrantLock#unlock底层调用了java.util.concurrent.locks.AbstractQueuedSynchronizer#release方法
在java.util.concurrent.locks.ReentrantLock.Sync#tryRelease方法中,当前AQS的state字段减去参数arg,当state为0时,释放锁,唤醒其他线程。

进入java.util.concurrent.locks.AbstractQueuedSynchronizer#unparkSuccessor可看出先从头部开始取一个节点并unpark,取不到的话再从队尾开始取节点并unpark
java.util.concurrent.locks.Condition
使用示例
Condition condition = lock.newCondition();
condition.await();
System.out.println("等待结束!");
condition.signal();
Condition主要是用于线程的主动阻塞,类似Object.wait()。参考java.lang.Thread.State线程状态
/**
* A thread state. A thread can be in one of the following states:
* <ul>
* <li>{@link #NEW}<br>
* A thread that has not yet started is in this state.
* </li>
* <li>{@link #RUNNABLE}<br>
* A thread executing in the Java virtual machine is in this state.
* </li>
* <li>{@link #BLOCKED}<br>
* A thread that is blocked waiting for a monitor lock
* is in this state.
* </li>
* <li>{@link #WAITING}<br>
* A thread that is waiting indefinitely for another thread to
* perform a particular action is in this state.
* </li>
* <li>{@link #TIMED_WAITING}<br>
* A thread that is waiting for another thread to perform an action
* for up to a specified waiting time is in this state.
* </li>
* <li>{@link #TERMINATED}<br>
* A thread that has exited is in this state.
* </li>
* </ul>
*
* <p>
* A thread can be in only one state at a given point in time.
* These states are virtual machine states which do not reflect
* any operating system thread states.
*
* @since 1.5
* @see #getState
*/
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
java层面定义了线程状态NEW,RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED。
Condition.await()和ReentrantLock.lock()底层都调用了LockSupport.park,所以他们的状态应该都是WAITING。

进入java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#await()
在进入java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#addConditionWaiter中可以看出,每个ConditionObject维护了一个单项链表,其中每个Node封装了线程信息,将当前线程封装节点加入Condition中的等待队列(这里队列和链表同义)。
java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#await()第2036行在阻塞前先释放锁,激活另一个在就绪队列中的节点(AQS中的双向链表)。
第2038中判断当前节点是否在AQS中的双向链表中,如在AQS中的双向链表,说明已被其他线程调用condition.signal()释放,否则阻塞当前线程,
第2040行进入到
java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#checkInterruptWhileWaiting再进入java.util.concurrent.locks.AbstractQueuedSynchronizer#transferAfterCancelledWait

可以看出这段代码是为了处理线程中断Thread.interrupt()和线程被激活ConditionObject.signal()同时发生的情况。

188

被折叠的 条评论
为什么被折叠?



