6. LockSupport

2019-03-15  本文已影响0人  shallowinggg

回顾前面部分的源码分析,当需要阻塞或唤醒一个线程的时候,都会使用LockSupport工具来完成相应工作。LockSupport定义了一组公共静态方法,这些方法提供了最基本的线程阻塞和唤醒公共,而LockSupport也成为构建同步组件的基础工具。

LockSupport定义了一组以park开头的方法用来阻塞当前线程,以及upark方法用来唤醒线程。这些方法如下所示:

方法名称 描述
void park() 阻塞当前线程,如果调用unpark(Thread)或者当前线程被中断,才能从park()方法返回
void parkNanos(long nanos) 阻塞当前线程,最长不超过nanos纳秒,返回条件在park()的基础上增加了超时返回
void parkUntil(long deadline) 阻塞当前线程,直到deadline
void unpark(Thread thread) 唤醒处于阻塞的线程thread

在Java 6新增了void park(Object blocker), void parkNanos(Object blocker, long nanos), void parkUntil(Object blocker, long deadline)三个方法,用以实现阻塞当前线程的功能,其中参数blocker是用来标识当前线程在在等待的对象(以下称阻塞对象),该对象主要用于问题排查和系统监控。

下面的示例中,将对比parkNanos(long nanos)parkNanos(Object blocker, long nanos)方法来展示阻塞对象blocker的用处,代码片段和线程dump如下:

对比项\方法 parkNanos(long nanos) parkNanos(Object blocker, long nanos)
代码片段 LockSupport.parkNanos(TimeUnit.
SECONDS.toNanos(10))
LockSupport.parkNanos(test, TimeUnit.SECONDS.toNanos(10));
线程
dump
结果
"main" #1 prio=5 os_prio=0 tid=
0x0000025636fb9000 nid=0x1494 waiting
on condition [0x000000bbe3fff000]
java.lang.Thread.State:
TIMED_WAITING (parking)
at jdk.internal.misc.Unsafe.park
(java.base@10.0.2/Native Method)
at java.util.concurrent.locks.LockSupport.
parkNanos(java.base@10.0.2/
LockSupport.java:357)
"main" #1 prio=5 os_prio=0 tid=0x000002b0ceda8800 nid=0x724 waiting on condition [0x000000c6acafe000]
java.lang.Thread.State: TIMED_WAITING (parking)
at jdk.internal.misc.Unsafe.park(java.base
@10.0.2/Native Method)
- parking to wait for <0x00000006d119f9d8>
(a p5.LockSupportTest)

at java.util.concurrent.locks.LockSupport.parkNanos
(java.base@10.0.2/LockSupport.java:234)

从表中的线程dump结果可以看出,代码片段的内容是阻塞当前线程10s,但从线程dump结果可以看出,有阻塞对象的parkNanos方法能够传递给开发人员更多的线程信息。这是由于java 5之前,在线程阻塞(使用synchronized关键字)在一个对象上时,通过线程dump能够查看到该线程的阻塞对象,方便问题定位,而在java 5推出的Lock等并发工具时却遗漏了这一点,致使线程dump时无法提供阻塞对象的信息。因此,在java 6中,LockSupport新增了上述三个含有阻塞对象的park方法。

如果遗忘了如果进行线程dump操作,这里再温习一下。
运行测试方法(不一定是"main")后,在终端输入jps命令:
10964
2740 Launcher
9224 Program
12956 LockSupportTest
14300 KotlinCompileDaemon
7740 Jps

从中找到测试类对应的线程id,此处是 12956,然后终端输入jstack 12956,即可输出线程dump信息,然后从中寻找到对应测试方法的信息,此处为"main" #1 prio=5 os_prio=0 tid=0x0000025636fb9000 nid=0x1494 .....

上一篇 下一篇

猜你喜欢

热点阅读