Bootstrap

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;   // xorshift
            r ^= 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 API
    private 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);
        }
    }

}

;