LockSupport的一点理解

类LockSupport是用于创建锁和其他同步类的基本线程阻塞原语。JDK中大量的线程阻塞和唤醒都是使用LockSupport来实现的。

每个使用LockSupport的线程都会关联一个许可证(permit)。如果某个线程持有许可证,则该线程调用park方法会立即返回,并且消费掉这个许可证;否则该线程会被阻塞。调用unpark方法会让对应的线程拥有许可证(注意:许可证不会被累加,每个线程最多持有一个许可证)。LockSupport类的park方法和unpark方法分别用于阻塞线程和唤醒线程。需要注意的是调用LockSupport.park方法的线程被中断会导致park方法返回,park方法也可能会因为其他的原因而返回(例如虚假唤醒)。所以通常来说应该在循环里调用park方法,并在park放唤醒之后重新检查是否符合唤醒的条件。如下所示:

while(!canProceed()) {
...
LockSupport.park().
...
}

LockSupport的park方法也支持blocker参数,该参数可以帮助诊断工具来获知线程阻塞的原因。例如使用jstack工具会会打印blocker参数,如下所示:

"Thread-0" #10 prio=5 os_prio=0 tid=0x000000001b586800 nid=0x37f0 waiting on condition [0x000000001c0ae000]
java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000d603a6e8> (a test.TestLockSupport$1)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at test.TestLockSupport$1.run(TestLockSupport.java:21)  

使用LockSupport来阻塞和唤醒线程的优势:

  1. 使用Object的wait和notify方法时,需要在sync代码块里,而且wait和notify方法是有调用顺序的(比如先调用wait然后再调用notify),而LockSupport并不需要在sync代码块中使用,并且因为许可证(permit)的存在,可以先调用unpark方法,然后再调用park方法。但是LockSupport并不意味着可以取代wait和notify方法,LockSupport在调用unpark方法中需要传递thread而且必须是要已启动的。wait是调用对象的方法,和对象的绑定,线程间不需要感知彼此的存在。

值的注意的是LockSupport的Javadoc中有一段英文:

Methods park and unpark provide efficient means of blocking and unblocking threads that do not encounter the problems that cause the deprecated methods Thread.suspend and Thread.resume to be unusable for such purposes: Races between one thread invoking park and another thread trying to unpark it will preserve liveness, due to the permit.

这段英文其实是说park和unpark方法不会遇到弃用方法Thread.suspend和Thread.resume需要注意调用顺序的问题。第一次看到这个英文长句子的时候一直没有明白他的意思,因此特此记录一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值