Java Lock LockSupport 源码
前言
相关系列
- 《Java & Lock & 目录》(持续更新)
- 《Java & Lock & LockSupport & 源码》(学习过程/多有漏误/仅作参考/不再更新)
- 《Java & Lock & LockSupport & 总结》(学习总结/最新最准/持续更新)
- 《Java & Lock & LockSupport & 问题》(学习解答/持续更新)
源码
/** ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*********************//******* Written by Doug Lea with assistance from members of JCP JSR-166* Expert Group and released to the public domain, as explained at* http://creativecommons.org/publicdomain/zero/1.0/*/package juc.locks;import juc.Semaphore;
import sun.misc.Unsafe;import java.util.concurrent.ThreadLocalRandom;/*** Basic thread blocking primitives for creating locks and other synchronization classes.* 用于创建锁和其它同步类的基本线程阻塞原语。* <p>* This class associates, with each thread that uses it, a permit (in the sense of the* {@link Semaphore Semaphore} class). A call to {@code park} will return immediately if the permit is available,* consuming it in the process; otherwise it <em>may</em> block. A call to {@code unpark} makes the permit available,* if it was not already available. (Unlike with Semaphores though, permits do not accumulate. There is at most one.)* 该类与每个使用它的线程关联一个许可(从信号量类的角度上看)。如果许可可用则调用一次park()方法将立即返回,并* 在过程中消费它;否则它将可能阻塞。如果许可不可用,则调用一次unpark()方法可使得其可用。(但是不像信号量,许* 可无法累积。最多只能有一个。)* <p>* Methods {@code park} and {@code unpark} provide efficient means of blocking and unblocking threads that do not* encounter the problems that cause the deprecated methods {@code Thread.suspend} and {@code Thread.resume} to* beunusable for such purposes: Races between one thread invoking {@code park} and another thread trying to* {@code unpark} it will preserve liveness, due to the permit. Additionally, {@code park} will return if the caller's* threadwas interrupted, and timeout versions are supported. The {@code park} method may also return at any other* time, for "no reason", so in general must be invoked within a loop that rechecks conditions upon return. In this sense* {@code park}serves as an optimization of a "busy wait" that does not waste as much time spinning, but must be* paired with an {@code unpark} to be effective.* 方法park和unpark提供了阻塞和解除阻塞线程的有效方法,这些方法不会遇到导致已弃用方法suspend和resume对于如此* 目的无用的问题:在线程调用park方法与其它线程尝试unpark它之间竞争将由于许可而保持活性。此外,如果调用者的线* 程已被中断,以及支持超时版本则park将返回。park方法也可能在任意其它时间无理由的返回,所以通常必须在返回后检* 查条件的循环中被调用。从这个角度上看park方法作为忙等待的优化手段不会浪费太多自旋时间,但必须与一个unpark方* 法成对使用以令之有效。* <p>* The three forms of {@code park} each also support a {@code blocker} object parameter. This object is recorded while* the thread is blocked to permit monitoring and diagnostic tools to identify the reasons that threads are blocked. (Such* tools may access blockers using method {@link #getBlocker(Thread)}.) The use of these forms rather than the original* forms without this parameter is strongly encouraged. The normal argument to supply as a {@code blocker} within a* lock implementation is {@code this}.* park方法的三种格式每个都支持一个阻塞者对象参数。该对象在线程在线程阻塞期间被记录,以允许监视器和诊断工具识* 别线程阻塞的原因。(该工具可能访问使用getBlocker(Thread)方法访问阻塞者)。强烈鼓励使用这些格式而不是原本没有* 参数的原始格式。该常规参数用于在一个锁实现中供应一个阻塞者。* <p>* These methods are designed to be used as tools for creating higher-level synchronization utilities, and are not in* themselves useful for most concurrency control applications. The {@code park} method is designed for use only in* constructions of the form:* 这些方法被设计用于作为创建更高等级的同步程序的工具,并且它们本身对于大多数并发控制应用程序并没有用(意思是* 不会在API中使用相应的方法保证线程安全,而是使用基于它们创建的线程安全工具保证线程安全)。park方法被设计只在* 以下格式中构造:* <pre> {@code* while (!canProceed()) { ... LockSupport.park(this); }}</pre>* <p>* where neither {@code canProceed} nor any other actions prior to the call to {@code park} entail locking or blocking.* Because only one permit is associated with each thread, any intermediary uses of {@code park} could interfere with* its intended effects.* 其中即不是canProceed方法也不是任意其它优先于park方法的活动都需要加锁或阻塞(意思是循环中位于park方法之后的* 代码都必须是线程安全的...妈的什么鬼英语)。因为线程只关联一个许可,因此任意park方法的中间调用都会干涉它的预* 期效果(简而言之就是要要避免外部干扰)。** <p>* <b>Sample Usage.</b> Here is a sketch of a first-in-first-out non-reentrant lock class:* 简单用法。这是一个先入先出非重入锁类的草图:* <pre> {@code* class FIFOMutex {* // ---- 原子布尔,作为锁使用。* private final AtomicBoolean locked = new AtomicBoolean(false);* // ---- 等待者队列。* private final Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();** // ---- 加锁。* public void lock() {* // ---- 经线程加入等待者集中。* boolean wasInterrupted = false;* Thread current = Thread.currentThread();* waiters.add(current);** // Block while not first in queue or cannot acquire lock* // 在非队列首个线程或无法获取锁的情况下阻塞** while (waiters.peek() != current || !locked.compareAndSet(false, true)) {* LockSupport.park(this);* if (Thread.interrupted())* // ignore interrupts while waiting* // 忽略在等待期间的中断(即该方法在设计上是不允许被中断的)* wasInterrupted = true;* }* // ---- 退出循环后,将当前线程从等待者集中移除。* waiters.remove();* // reassert interrupt status on exit* // 在退出时重设中断状态。* if (wasInterrupted)* current.interrupt();* }** public void unlock() {* locked.set(false);* // ---- 唤醒等待者集中的首个线程。* LockSupport.unpark(waiters.peek());* }* }}</pre>*/
public class LockSupport {/*** @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* ----* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 初始化锁支持者* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ----*/private LockSupport() {// Cannot be instantiated.// 无法(外部)实例化}/*** @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 设置阻塞者* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 为指定线程设置指定阻塞者* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法直接通过CAS操作完成。*/private static void setBlocker(Thread t, Object arg) {// Even though volatile, hotspot doesn't need a write barrier here.// 虽然易变,但热点在这里不需要一个写屏障。UNSAFE.putObject(t, parkBlockerOffset, arg);}/*** Makes available the permit for the given thread, if it was not already available. If the thread was blocked on* {@code park} then it will unblock. Otherwise, its next call to {@code park} is guaranteed not to block. This* operation is not guaranteed to have any effect at all if the given thread has not been started.* 如果指定线程尚未可用,则令其许可可用。如果线程它因为park方法而阻塞则它将解除阻塞。否则,它的下次park方* 法调用将不保证阻塞。如果指定线程尚未启动则该操作无法保证在任意情况下都有效果。** @param thread the thread to unpark, or {@code null}, in which case this operation has no effect* 用于释放的线程,或者为null,在该情况下该操作没有效果* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 解除停放* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 为指定线程分配一个许可,如果指定线程因为许可负债(-1)而处于等待状态,则将因为负债被清零而恢复运行;如果* 指定线程因为许可平衡(0)而处于运行状态,则将因为许可结余(1)而不会在下一次许可消耗中进入等待状态。如果* 执行线程尚未启动则上述所有情况都不保证一定会发生。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法直接通过CAS机制实现。*/public static void unpark(Thread thread) {if (thread != null)UNSAFE.unpark(thread);}/*** Disables the current thread for thread scheduling purposes unless the permit is available.* 出于线程调度目的令当前线程无效,除非许可可用。* <p>* If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes* disabled for thread scheduling purposes and lies dormant until one of three things happens:* 如果许可可用则消费许可并立即返回;否则当前线程处于线程调度目的将变得无效,并且休眠至以下三种情况发生:* <ul>* <li>Some other thread invokes {@link #unpark unpark} with the current thread as the target; or* 某些其它线程将当前线程作为目标调用unpark方法;或者* <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or* 某些其它线程中断当前线程;或者* <li>The call spuriously (that is, for no reason) returns. </ul>* 该调用虚假地(无理由地)返回。* <p>* This method does <em>not</em> report which of these caused the method to return. Callers should re-check the* conditions which caused the thread to park in the first place. Callers may also determine, for example, the* interrupt status of the thread upon return.* 该方法不会记录什么导致方法返回。调用者首先应该重检查导致线程停泊的条件(是否满足)。调用者可能还要确定,* 例如,线程返回后的中断状态。** @param blocker the synchronization object responsible for this thread parking* 该同步对象负责当前线程的停泊* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 停泊* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 消耗指定线程的一个许可,消耗后如果指定线程许可负债(-1)则进入无限等待状态;直至因为信号、中断及虚假的原* 因而唤醒;否则直接返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法首先会为指定线程设置阻塞者,随后令之进入等待状态,如果被唤醒或进入等待状态失败则将阻塞者清除并返* 回。阻塞者的作用是令唤醒当前线程可以判断是否满足条件,功能是自定义的。* @since 1.6*/public static void park(Object blocker) {// ---- 方法首先会为指定线程设置阻塞者,随后令之进入等待状态,如果被唤醒或进入等待状态失败则将阻塞者清除// 并返回。阻塞者的作用是令唤醒当前线程可以判断是否满足条件,功能是自定义的。Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(false, 0L);setBlocker(t, null);}/*** Disables the current thread for thread scheduling purposes, for up to the specified waiting time, unless the permit* is available.* 出于调度线程的目的令当前线程无效,直至指定等待时间,除非许可可用。* <p>* If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes* disabled for thread scheduling purposes and lies dormant until one of four things happens:* 如果许可可用则消费许可并立即返回;否则当前线程处于线程调度目的将变得无效,并且休眠至以下四种情况发生:* <ul>* <li>Some other thread invokes {@link #unpark unpark} with the current thread as the target; or* 某些其它线程将当前线程作为目标调用unpark方法;或者* <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or* 某些其它线程中断当前线程;或者* <li>The specified waiting time elapses; or* 指定等待时间消逝;或者* <li>The call spuriously (that is, for no reason) returns. </ul>* 该调用虚假地(无理由地)返回。* </ul>** <p>* This method does <em>not</em> report which of these caused the method to return. Callers should re-check the* conditions which caused the thread to park in the first place. Callers may also determine, for example, the* interrupt status of the thread, or the elapsed time upon return.* 该方法不会记录什么导致方法返回。调用者首先应该重检查导致线程停泊的条件(是否满足)。调用者可能还要确定,* 例如,线程返回后的中断状态,或过期时间。** @param blocker the synchronization object responsible for this thread parking* 该同步对象负责当前线程的停泊* @param nanos the maximum number of nanoseconds to wait* 等待的最大纳秒时间* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 停泊纳秒* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 消耗指定线程的一个许可,消耗后如果指定线程许可负债(-1)则进入有限等待状态;直至因为信号、中断、超时及虚* 假的原因而唤醒;否则直接返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法首先会判断指定等待时间是否合法,合法则为指定线程设置阻塞者,随后令之进入等待状态,如果被唤醒或进* 入等待状态失败则将阻塞者清除并返回。* @since 1.6*/public static void parkNanos(Object blocker, long nanos) {if (nanos > 0) {Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(false, nanos);setBlocker(t, null);}}/*** Disables the current thread for thread scheduling purposes, until the specified deadline, unless the permit is available.* 出于调度线程的目的令当前线程无效,直至指定死亡线,除非许可可用。* <p>* If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes* disabled for thread scheduling purposes and lies dormant until one of four things happens:* 如果许可可用则消费许可并立即返回;否则当前线程处于线程调度目的将变得无效,并且休眠至以下四种情况发生:* <ul>* <li>Some other thread invokes {@link #unpark unpark} with the current thread as the target; or* 某些其它线程将当前线程作为目标调用unpark方法;或者* <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or* 某些其它线程中断当前线程;或者* <li>The specified waiting time elapses; or* 指定等待时间消逝;或者* <li>The call spuriously (that is, for no reason) returns. </ul>* 该调用虚假地(无理由地)返回。* </ul>* <p>* This method does <em>not</em> report which of these caused the method to return. Callers should re-check the* conditions which caused the thread to park in the first place. Callers may also determine, for example, the* interrupt status of the thread, or the current time upon return.* 该方法不会记录什么导致方法返回。调用者首先应该重检查导致线程停泊的条件(是否满足)。调用者可能还要确定,* 例如,线程返回后的中断状态,或过期时间。** @param blocker the synchronization object responsible for this thread parking* 该同步对象负责当前线程的停泊* @param deadline the absolute time, in milliseconds from the Epoch, to wait until* 从纪元到等待的绝对时间,以毫秒为单位* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 停泊直至* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 消耗指定线程的一个许可,消耗后如果指定线程许可负债(-1)则进入有限等待状态;直至因为信号、中断、超时及虚* 假的原因而唤醒;否则直接返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法首先会为指定线程设置阻塞者,随后令之进入等待状态,如果被唤醒或进入等待状态失败则将阻塞者清除并返* 回。* @since 1.6*/public static void parkUntil(Object blocker, long deadline) {Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(true, deadline);setBlocker(t, null);}/*** Returns the blocker object supplied to the most recent invocation of a park method that has not yet unblocked, or* null if not blocked. The value returned is just a momentary snapshot -- the thread may have since unblocked or* blocked on a different blocker object.* 返回由最近一次还未解除阻塞的park方法调用提供的阻塞者对象,或者如果未阻塞则为null。返回的值只是一个短暂的* 快照-- 该线程可能已解除阻塞或在另一个阻塞对象中阻塞。** @param t the thread 线程* @return the blocker 阻塞者* @throws NullPointerException if argument is null* 空指针异常:如果参数为null* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 获取阻塞者* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 获取当前线程的阻塞者。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ----* @since 1.6*/public static Object getBlocker(Thread t) {if (t == null)throw new NullPointerException();return UNSAFE.getObjectVolatile(t, parkBlockerOffset);}/*** Disables the current thread for thread scheduling purposes unless the permit is available.* 出于线程调度目的令当前线程无效,除非许可可用。* <p>* If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes* disabled for thread scheduling purposes and lies dormant until one of three things happens:* 如果许可可用则消费许可并立即返回;否则当前线程处于线程调度目的将变得无效,并且休眠至以下三种情况发生:* <ul>* <li>Some other thread invokes {@link #unpark unpark} with the current thread as the target; or* 某些其它线程将当前线程作为目标调用unpark方法;或者* <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or* 某些其它线程中断当前线程;或者* <li>The call spuriously (that is, for no reason) returns. </ul>* 该调用虚假地(无理由地)返回。* </ul>** <p>* This method does <em>not</em> report which of these caused the method to return. Callers should re-check the* conditions which caused the thread to park in the first place. Callers may also determine, for example, the* interrupt status of the thread upon return.* 该方法不会记录什么导致方法返回。调用者首先应该重检查导致线程停泊的条件(是否满足)。调用者可能还要确定,* 例如,线程返回后的中断状态。** @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 停泊* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 消耗指定线程的一个许可,消耗后如果指定线程许可负债(-1)则进入无限等待状态;直至因为信号、中断及虚假的原* 因而唤醒;否则直接返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ----*/public static void park() {UNSAFE.park(false, 0L);}/*** Disables the current thread for thread scheduling purposes, for up to the specified waiting time, unless the permit* is available.* 出于调度线程的目的令当前线程无效,直至指定等待时间,除非许可可用。** <p>* If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes* disabled for thread scheduling purposes and lies dormant until one of four things happens:* 如果许可可用则消费许可并立即返回;否则当前线程处于线程调度目的将变得无效,并且休眠至以下四种情况发生:* <ul>* <li>Some other thread invokes {@link #unpark unpark} with the current thread as the target; or* 某些其它线程将当前线程作为目标调用unpark方法;或者* <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or* 某些其它线程中断当前线程;或者* <li>The specified waiting time elapses; or* 指定等待时间消逝;或者* <li>The call spuriously (that is, for no reason) returns. </ul>* 该调用虚假地(无理由地)返回。* </ul>** <p>* This method does <em>not</em> report which of these caused the method to return. Callers should re-check the* conditions which caused the thread to park in the first place. Callers may also determine, for example, the* interrupt status of the thread, or the elapsed time upon return.* 该方法不会记录什么导致方法返回。调用者首先应该重检查导致线程停泊的条件(是否满足)。调用者可能还要确定,* 例如,线程返回后的中断状态,或过期时间。** @param nanos the maximum number of nanoseconds to wait* 等待的最大纳秒时间* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 停泊纳秒* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 消耗指定线程的一个许可,消耗后如果指定线程许可负债(-1)则进入有限等待状态;直至因为信号、中断、超时及虚* 假的原因而唤醒;否则直接返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ----*/public static void parkNanos(long nanos) {if (nanos > 0)UNSAFE.park(false, nanos);}/*** Disables the current thread for thread scheduling purposes, until the specified deadline, unless the permit is available.* 出于调度线程的目的令当前线程无效,直至指定死亡线,除非许可可用。* <p>* If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes* disabled for thread scheduling purposes and lies dormant until one of four things happens:* 如果许可可用则消费许可并立即返回;否则当前线程处于线程调度目的将变得无效,并且休眠至以下四种情况发生:* <ul>* <li>Some other thread invokes {@link #unpark unpark} with the current thread as the target; or* 某些其它线程将当前线程作为目标调用unpark方法;或者* <li>Some other thread {@linkplain Thread#interrupt interrupts} the current thread; or* 某些其它线程中断当前线程;或者* <li>The specified waiting time elapses; or* 指定等待时间消逝;或者* <li>The call spuriously (that is, for no reason) returns. </ul>* 该调用虚假地(无理由地)返回。* </ul>* <p>* This method does <em>not</em> report which of these caused the method to return. Callers should re-check the* conditions which caused the thread to park in the first place. Callers may also determine, for example, the* interrupt status of the thread, or the current time upon return.* 该方法不会记录什么导致方法返回。调用者首先应该重检查导致线程停泊的条件(是否满足)。调用者可能还要确定,* 例如,线程返回后的中断状态,或过期时间。** @param deadline the absolute time, in milliseconds from the Epoch, to wait until* 从纪元到等待的绝对时间,以毫秒为单位* @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 停泊直至* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 消耗指定线程的一个许可,消耗后如果指定线程许可负债(-1)则进入有限等待状态;直至因为信号、中断、超时及虚* 假的原因而唤醒;否则直接返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法首先会为指定线程设置阻塞者,随后令之进入等待状态,如果被唤醒或进入等待状态失败则将阻塞者清除并返* 回。*/public static void parkUntil(long deadline) {UNSAFE.park(true, deadline);}/*** Returns the pseudo-randomly initialized or updated secondary seed. Copied from ThreadLocalRandom due to package* access restrictions.* 虚假随机地返回初始化的或更新的次要个种子。由于包访问限制从ThreadLocalRandom中赋值。** @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------* 下个次要种子* @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------* 基于当前线程的次要种子生成新的次要种子并保存/返回。* @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------* ---- 方法首先会从当前线程中获取次要种子并判断是否为0,为0表示为初始值,为之随机分配一个值。但为了防止随机* 的数值为0需要在该情况下手动将之赋值为1;如果不为0则说明次要种子已经被更新过,基于其进行位运算已生成新的* 次要种子。* ---- 新的次要种子生成后将之重新保存至当前线程中并返回。*/static final int nextSecondarySeed() {int r;Thread t = Thread.currentThread();if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {// ---- 从线程中获取次要种子,如果不为0,说明已经经历过更新,直接进行位操作。r ^= r << 13; // xorshiftr ^= r >>> 17;r ^= r << 5;} else if ((r = ThreadLocalRandom.current().nextInt()) == 0)// avoid zero// 避免0// ---- 如果次要种子为0,说明为初始值,尚未经历过更新,因此为之分配一个随机数。但是为了防止其再次为0需// 要在其位0是手动赋值为1。r = 1;// ---- 新的次要种子被分配后,重新保存。UNSAFE.putInt(t, SECONDARY, r);return r;}// Hotspot implementation via intrinsics APIprivate static final Unsafe UNSAFE;private static final long parkBlockerOffset;private static final long SEED;private static final long PROBE;private static final long SECONDARY;static {try {UNSAFE = Unsafe.getUnsafe();Class<?> tk = Thread.class;parkBlockerOffset = UNSAFE.objectFieldOffset(tk.getDeclaredField("parkBlocker"));SEED = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSeed"));PROBE = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomProbe"));SECONDARY = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSecondarySeed"));} catch (Exception ex) {throw new Error(ex);}}}