请选择 进入手机版 | 继续访问电脑版
零一零零 门户 IT技术 Java并发 查看内容

Java并发编程之LookSupport

2020-7-3 16:22| 发布者: x0100| 查看: 1911| 评论: 0

摘要: java.util.concurrent 中源码频繁使用的 LockSupport 来阻塞线程和唤醒线程,如 AQS 的底层实现用到 LockSupport.park()方法和 LockSupport.unpark()方法。 LockSupport 到底是什么?同样是阻塞和唤醒线程为什么不用 ...


java.util.concurrent 中源码频繁使用的 LockSupport 来阻塞线程和唤醒线程,如 AQS 的底层实现用到 LockSupport.park()方法和 LockSupport.unpark()方法。

LockSupport 到底是什么?同样是阻塞和唤醒线程为什么不用 Object 的 wait()/notify 方法?

1. LockSupprot 方法介绍

LockSupport 提供 park()和 unpark()方法实现阻塞线程和解除线程阻塞。

阻塞线程:

  • void park():阻塞当前线程,如果调用 unpark 方法或者当前线程被中断,才能从 park()方法中返回

  • void park(Object blocker):功能同方法 1,入参增加一个 Object 对象,用来记录导致线程阻塞的阻塞对象,方便进行问题排查;

  • void parkNanos(long nanos):阻塞当前线程,最长不超过 nanos 纳秒,增加了超时返回的特性;

  • void parkNanos(Object blocker, long nanos):功能同方法 3,入参增加一个 Object 对象,用来记录导致线程阻塞的阻塞对象,方便进行问题排查;

  • void parkUntil(long deadline):阻塞当前线程,直到 deadline;

  • void parkUntil(Object blocker, long deadline):功能同方法 5,入参增加一个 Object 对象,用来记录导致线程阻塞的阻塞对象,方便进行问题排查;

每个 park 方法都对应有一个带有 Object 阻塞对象的重载方法。增加了一个 Object 对象作为参数,此对象在线程受阻塞时被记录,以允许监视工具和诊断工具确定线程受阻塞的原因。

唤醒线程:

void unpark(Thread thread):唤醒处于阻塞状态的指定线程

使用举例

  1. public class LockSupportDemo {
  2. public static void main(String[] args) {
  3. Thread thread = new Thread(() -> {
  4. LockSupport.park();
  5. System.out.println("thread线程被唤醒");
  6. });
  7. thread.start();
  8. try {
  9. Thread.sleep(3000);
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. }
  13. LockSupport.unpark(thread);
  14. }
  15. }
  1. thread线程park阻塞。
  2. 主线程sleep3s之后,unpark(thread)。
  3. thread被唤醒,输出"thread线程被唤醒"

2. 原理

每个线程都会与一个许可关联,这个许可对应一个 Parker 的实例,Parker 有一个 int 类型的属性_count。

park()方法:

  1. 将_count 变为 0

  2. 如果原_count==0,将线程阻塞

unpark()方法:

  1. 将_count 变为 1

  2. 如果原_count==0,将线程唤醒

3. 特殊之处

  1. Object 的 wait()/notify 方法需要获取到对象锁之后在同步代码块里才能调用,而 LockSupport 不需要获取锁。所以使用 LockSupport 线程间不需要维护一个共享的同步对象,从而实现了线程间的解耦。

  2. unark()方法可提前 park()方法调用,所以不需要担心线程间执行的先后顺序。

  3. 多次调用 unpark()方法和调用一次 unpark()方法效果一样,因为 unpark 方法是直接将_counter 赋值为 1,而不是加 1。

  4. 许可不可重入,也就是说只能调用一次 park()方法,如果多次调用 park()线程会一直阻塞。


鲜花

握手

雷人

路过

鸡蛋

最新评论


QQ|Archiver|手机版|小黑屋| 零一零零 ( 京ICP备20003964号 ) |网站地图

GMT+8, 2020-10-31 19:03 , Processed in 0.035057 second(s), 17 queries .

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

返回顶部