模块 java.base

类 LockSupport

java.lang.Object
java.util.concurrent.locks.LockSupport

public class LockSupport extends Object
用于创建锁和其他同步类的基本线程阻塞原语。

此类与使用它的每个线程关联一个许可(在 Semaphore 类的意义上)。如果许可可用,对 park 的调用将立即返回,并在此过程中消耗它;否则它may块。如果许可尚不可用,则调用 unpark 可使许可可用。 (虽然与信号量不同,许可不会累积。最多只有一个。)可靠的使用需要使用易失性(或原子)变量来控制何时停放或取消停放。对这些方法的调用顺序是根据易失性变量访问来维护的,但不一定是非易失性变量访问。

方法 parkunpark 提供了阻塞和解除阻塞线程的有效方法,这些线程不会遇到导致已弃用方法 Thread.suspendThread.resume 无法用于此类目的的问题:一个线程调用 park 和另一个线程尝试调用 unpark 之间的竞争将保持活性,由于许可证。此外,如果调用者的线程被中断,park 将返回,并且支持超时版本。 park 方法也可能在任何其他时间“无故”返回,因此通常必须在返回时重新检查条件的循环中调用。从这个意义上说,park 是对“忙等待”的优化,它不会浪费太多时间,但必须与 unpark 配对才能有效。

park 的三种形式各自还支持一个 blocker 对象参数。在线程被阻塞时记录此对象,以允许监视和诊断工具识别线程被阻塞的原因。 (此类工具可能会使用方法 getBlocker(Thread) 访问阻止程序。)强烈建议使用这些形式而不是没有此参数的原始形式。在锁实现中作为 blocker 提供的正常参数是 this

这些方法旨在用作创建更高级别同步实用程序的工具,它们本身对大多数并发控制应用程序没有用处。 park 方法仅用于以下形式的构造:

 
 while (!canProceed()) {
  // ensure request to unpark is visible to other threads
  ...
  LockSupport.park(this);
 } 
其中,在调用 park 之前,发布请求取消停放的线程没有执行任何操作,需要锁定或阻塞。因为只有一个许可与每个线程相关联,所以 park 的任何中间使用,包括通过类加载隐式使用,都可能导致线程无响应(“丢失的解锁”)。

示例用法。这是一个先进先出的不可重入锁类的草图:

 
 class FIFOMutex {
  private final AtomicBoolean locked = new AtomicBoolean(false);
  private final Queue<Thread> waiters
   = new ConcurrentLinkedQueue<>();

  public void lock() {
   boolean wasInterrupted = false;
   // publish current thread for unparkers
   waiters.add(Thread.currentThread());

   // Block while not first in queue or cannot acquire lock
   while (waiters.peek() != Thread.currentThread() ||
      !locked.compareAndSet(false, true)) {
    LockSupport.park(this);
    // ignore interrupts while waiting
    if (Thread.interrupted())
     wasInterrupted = true;
   }

   waiters.remove();
   // ensure correct interrupt status on return
   if (wasInterrupted)
    Thread.currentThread().interrupt();
  }

  public void unlock() {
   locked.set(false);
   LockSupport.unpark(waiters.peek());
  }

  static {
   // Reduce the risk of "lost unpark" due to classloading
   Class<?> ensureLoaded = LockSupport.class;
  }
 } 
自从:
1.5
  • 方法总结

    修饰符和类型
    方法
    描述
    static Object
    返回提供给最近一次调用尚未解除阻塞的 park 方法的阻塞对象,如果未被阻塞则返回 null。
    static void
    park()
    除非许可可用,否则出于线程调度目的禁用当前线程。
    static void
    park(Object blocker)
    除非许可可用,否则出于线程调度目的禁用当前线程。
    static void
    parkNanos(long nanos)
    出于线程调度目的禁用当前线程,直到指定的等待时间,除非许可可用。
    static void
    parkNanos(Object blocker, long nanos)
    出于线程调度目的禁用当前线程,直到指定的等待时间,除非许可可用。
    static void
    parkUntil(long deadline)
    出于线程调度目的禁用当前线程,直到指定的截止日期,除非许可可用。
    static void
    parkUntil(Object blocker, long deadline)
    出于线程调度目的禁用当前线程,直到指定的截止日期,除非许可可用。
    static void
    设置要由当前线程调用 getBlocker 返回的对象。
    static void
    unpark(Thread thread)
    使给定线程的许可可用(如果它尚不可用)。

    在类 java.lang.Object 中声明的方法

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • 方法详情

    • setCurrentBlocker

      public static void setCurrentBlocker(Object  blocker)
      设置要由当前线程调用 getBlocker 返回的对象。在从非公共对象调用 park() 的无参数版本之前,可以使用此方法,从而允许进行更有用的诊断,或保持与以前的阻塞方法实现的兼容性。阻止程序的先前值在阻止后不会自动恢复。要获得 park(b } 的效果,请使用 setCurrentBlocker(b); park(); setCurrentBlocker(null);
      参数:
      blocker - 阻塞对象
      自从:
      14
    • unpark

      public static void unpark(Thread  thread)
      使给定线程的许可可用(如果它尚不可用)。如果线程在 park 上被阻塞,那么它将解除阻塞。否则,它对 park 的下一次调用保证不会阻塞。如果给定线程尚未启动,则不能保证此操作有任何效果。
      参数:
      thread - 要取消停放的线程,或 null ,在这种情况下此操作无效
    • park

      public static void park(Object  blocker)
      除非许可可用,否则出于线程调度目的禁用当前线程。

      如果许可证可用,则使用它并立即返回调用;否则,当前线程出于线程调度目的而被禁用并处于休眠状态,直到发生以下三种情况之一:

      • 一些其他线程以当前线程作为目标调用 unpark ;或者
      • 一些其他线程中断当前线程;或者
      • 调用虚假地(即无缘无故地)返回。

      此方法会not 报告其中哪些导致该方法返回。调用者应该首先重新检查导致线程停放的条件。调用者还可以确定,例如,返回时线程的中断状态。

      参数:
      blocker - 负责此线程停放的同步对象
      自从:
      1.6
    • parkNanos

      public static void parkNanos(Object  blocker, long nanos)
      出于线程调度目的禁用当前线程,直到指定的等待时间,除非许可可用。

      如果指定的等待时间为零或负数,则该方法不执行任何操作。否则,如果许可证可用,则使用它并立即返回调用;否则,当前线程出于线程调度目的而被禁用并处于休眠状态,直到发生以下四种情况之一:

      • 一些其他线程以当前线程作为目标调用 unpark ;或者
      • 一些其他线程中断当前线程;或者
      • 指定的等待时间过去了;或者
      • 调用虚假地(即无缘无故地)返回。

      此方法会not 报告其中哪些导致该方法返回。调用者应该首先重新检查导致线程停放的条件。调用者还可以确定,例如,线程的中断状态,或返回时经过的时间。

      参数:
      blocker - 负责此线程停放的同步对象
      nanos - 等待的最大纳秒数
      自从:
      1.6
    • parkUntil

      public static void parkUntil(Object  blocker, long deadline)
      出于线程调度目的禁用当前线程,直到指定的截止日期,除非许可可用。

      如果许可证可用,则使用它并立即返回调用;否则,当前线程出于线程调度目的而被禁用并处于休眠状态,直到发生以下四种情况之一:

      • 一些其他线程以当前线程作为目标调用 unpark ;或者
      • 一些其他线程中断当前线程;或者
      • 指定的截止日期过去了;或者
      • 调用虚假地(即无缘无故地)返回。

      此方法会not 报告其中哪些导致该方法返回。调用者应该首先重新检查导致线程停放的条件。调用者还可以确定,例如,线程的中断状态,或返回时的当前时间。

      参数:
      blocker - 负责此线程停放的同步对象
      deadline - 等待的绝对时间,从纪元开始以毫秒为单位
      自从:
      1.6
    • getBlocker

      public static Object  getBlocker(Thread  t)
      返回提供给最近一次调用尚未解除阻塞的 park 方法的阻塞对象,如果未被阻塞则返回 null。返回的值只是一个瞬间快照——线程可能在不同的阻塞对象上解除阻塞或阻塞。
      参数:
      t - 线程
      返回:
      阻碍者
      抛出:
      NullPointerException - 如果参数为空
      自从:
      1.6
    • park

      public static void park()
      除非许可可用,否则出于线程调度目的禁用当前线程。

      如果许可证可用,则使用它并立即返回调用;否则,当前线程出于线程调度目的而被禁用并处于休眠状态,直到发生以下三种情况之一:

      • 一些其他线程以当前线程作为目标调用 unpark ;或者
      • 一些其他线程中断当前线程;或者
      • 调用虚假地(即无缘无故地)返回。

      此方法会not 报告其中哪些导致该方法返回。调用者应该首先重新检查导致线程停放的条件。调用者还可以确定,例如,返回时线程的中断状态。

    • parkNanos

      public static void parkNanos(long nanos)
      出于线程调度目的禁用当前线程,直到指定的等待时间,除非许可可用。

      如果指定的等待时间为零或负数,则该方法不执行任何操作。否则,如果许可证可用,则使用它并立即返回调用;否则,当前线程出于线程调度目的而被禁用并处于休眠状态,直到发生以下四种情况之一:

      • 一些其他线程以当前线程作为目标调用 unpark ;或者
      • 一些其他线程中断当前线程;或者
      • 指定的等待时间过去了;或者
      • 调用虚假地(即无缘无故地)返回。

      此方法会not 报告其中哪些导致该方法返回。调用者应该首先重新检查导致线程停放的条件。调用者还可以确定,例如,线程的中断状态,或返回时经过的时间。

      参数:
      nanos - 等待的最大纳秒数
    • parkUntil

      public static void parkUntil(long deadline)
      出于线程调度目的禁用当前线程,直到指定的截止日期,除非许可可用。

      如果许可证可用,则使用它并立即返回调用;否则,当前线程出于线程调度目的而被禁用并处于休眠状态,直到发生以下四种情况之一:

      • 一些其他线程以当前线程作为目标调用 unpark ;或者
      • 一些其他线程中断当前线程;或者
      • 指定的截止日期过去了;或者
      • 调用虚假地(即无缘无故地)返回。

      此方法会not 报告其中哪些导致该方法返回。调用者应该首先重新检查导致线程停放的条件。调用者还可以确定,例如,线程的中断状态,或返回时的当前时间。

      参数:
      deadline - 等待的绝对时间,从纪元开始以毫秒为单位