LockSupport随笔

LockSupport随笔,第1张

1.public static void park()

为线程调度目的禁用当前线程,除非许可可用。

如果许可证是可用的,那么它将被消耗,并且呼叫立即返回;否则,当前线程将被禁用,并处于休眠状态,直到发生以下三种情况之一:

1.其他一些线程以当前线程为目标调用unpark();

2.其他线程中断当前线程;

3.调用虚假地(即没有理由地)返回。

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

2.public static void unpark(Thread thread)

使给定线程的许可可用(如果该线程尚未可用)。如果线程在park()上被阻塞,那么它将解除阻塞。否则,它对park()的下一次调用保证不会被阻塞。如果给定的线程没有启动,这个 *** 作根本不能保证有任何效果。

3.public static void parkNanos(long nanos)

为线程调度目的禁用当前线程,直到指定的等待时间,除非许可可用。

如果指定的等待时间为零或负值,则该方法不执行任何 *** 作。否则,如果许可证是可用的,那么它将被消耗,并且调用立即返回;否则,当前线程将被禁用,并处于休眠状态,直到发生以下四种情况之一:

1.其他一些线程以当前线程为目标调用unpark;

2.其他线程中断当前线程;

3.指定的等待时间过去;

4.调用虚假地(即没有理由地)返回。

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

4.public static void parkUntil(long deadline)

为线程调度目的禁用当前线程,直到指定的截止日期,除非许可可用。

如果许可证是可用的,那么它将被消耗,并且呼叫立即返回;否则,当前线程将被禁用,并处于休眠状态,直到发生以下四种情况之一:

1.其他一些线程以当前线程为目标调用unpark;

2.其他线程中断当前线程;

3.规定的期限过去了;

4.调用虚假地(即没有理由地)返回。

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

5.Tips

1.当线程被park阻塞后中断,或在调用park前被中断,线程会继续执行,不会有InterruptedException抛出,也不会清除中断标记

2.park/unpark可以实现和wait/notify相当的效果,但是二者并无交集,notify对park线程不起作用,unpark亦对wait不起作用

3.相较于wait/notify,park/unpark不需要获取某个对象的锁,不强制要求在同步代码块中才能使用;虽然park/unpark不需要获取某个对象的锁,但是当有锁的情况下park并不会释放锁

4.相较于wait/notify,park/unpark可以唤醒指定的线程,实现更精准的线程调度

5.park方法有一套参数带blocker的变体,blocker和当前线程相关联,其作用是在dump线程的时候看到阻塞对象的信息,主要用于问题的排查;LockSupport提供了blocker的getter/setter;blocker仅存在于线程因park阻塞的期间(在park中实现),且其并不在Java层面存储

6.LockSupport和CAS是AQS框架的两大基石

7.park/unpark的工作模式非常类似生产者/消费者模型

6.文档翻译

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

这个类与使用它的每个线程关联一个许可证(在Semaphore类的意义上)。如果许可证可用,对park()的调用将立即返回,并在进程中使用它;否则它可能会阻塞。如果许可证尚未可用,调用unpark()将使其可用。(与信号量不同的是,许可证不会累积。最多有一个。)可靠的使用需要使用volatile(或原子)变量来控制何时使用park()或unpark()。这些方法的调用顺序是根据易失性变量的访问来维持的,但非易失性变量的访问就不一定了。

方法park()和unpark()提供了阻塞和解除阻塞的有效方法,这些方法不会遇到导致已弃用的方法Thread.suspend()和Thread.resume()在这种目的下无法使用的问题:调用park()的一个线程和试图取消park()的另一个线程之间的竞争,由于许可,它将保持活动。此外,如果调用者的线程被中断,park()将返回,并且支持超时版本。park()方法也可以在任何其他时间“无理由”返回,因此通常必须在返回时重新检查条件的循环中调用。从这个意义上说,park()可以作为“繁忙等待”的优化,它不会浪费太多时间旋转,但必须与unpark()结合使用才能有效。

park()的三种形式都支持一个拦截器对象参数。在线程阻塞时记录此对象,以便监视和诊断工具识别线程阻塞的原因。(这些工具可以使用getBlocker(Thread)方法访问拦截器。)强烈建议使用这些形式而不是没有此参数的原始形式。在锁实现中作为阻塞器提供的通常参数是这样的。

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

while (!canProceed()) {
    // ensure request to unpark is visible to other threads
    ...
    LockSupport.park(this);  
}

在调用park()之前,向unpark()发布请求的线程没有任何动作,这就需要锁定或阻塞。因为只有一个许可证与每个线程相关联,任何park()的中间使用,包括通过类加载隐式地使用,都可能导致线程没有响应。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/729389.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-27
下一篇 2022-04-27

发表评论

登录后才能评论

评论列表(0条)

保存