Locksupport 理解
LockSupport 的构造方法都是私有的。对于创建锁或者其他同步类是基本的线程阻塞原语。
LockSupport 与使用它的线程 以及 permit 关联,如果permit 可用的话,park 函数调用使得会立即返回,并消费掉一个permit,否则线程会阻塞。如果之前permit 不可用的时候 即数量为0 的时候,unpark 会使得permit 再次可用,注意与semaphore不同,permit数量不会累积,其数量最多为1 个。
park
和unpark
用来阻塞或者恢复线程不会遇到Thread.suspend
和Thread.resume
引发的问题 。Thread.suspend
和Thread.resume
对于这样的情况无能为力:一个线程调用park 另一个线程尝试调用unpark
即二者存在某种竞争关系,此时就不应该使用suspend和resume
(因为suspend
只是单纯的挂起线程不会释放线程占用的锁,所以其挂起后其他等待他持有的锁的线程不能得到执行,直到其他线程调用Thread.resume
但是 因为存在竞争关系 所以Thread.resume
可能先执行 所以 导致后执行的suspend 一直阻塞 发生死锁)而park
和unpark
因为permit
的变量的引入,即使先调用unpark
其permit
在不可用 即数量为0 的情况下 会变为1.使得park
会立即消费permit
从而不会导致竞争引发的阻塞。
另外 调用park
的 线程可以响应中断 从而不会继续阻塞 而且提供的超时的park
版本。
另外 park
可能会无缘无故的返回 ,所以通常建议使用循环检查条件 来判断其是否还是否需要再次park
.
另外 一定要将park
与unpark
成对使用
park 解释
三种形式的park 支持一个blocker 参数,该参数可以记录线程因为什么而阻塞,从而可以便于诊断和分析。getBlocker(Thread)
可以获取到其blockers 对象。这些函数被设计用来为更高级的同步工具提供支撑。
park(Object blocker) 会调用UNSAFE.park()
进行阻塞,同时会设置调用线程的blocker .调用后 线程会处于休眠状态,并且不参与线程调度。
LockSupport.parkNanos(Object blocker,long nanos) 同样会使得线程处于休眠状态(如果线程没有permit 的话)。同样 若其他线程使得该线程中断 或者其他线程unpark 该线程 都会使得该线程继续运行。
其中 UNSAFE.park(boolean b,long v)第一个参数代表是否是绝对时间,第二个参数是时间。如果为true代表绝对时间,如果为false 代表为相对现在的时间。
所以我们在源代码中经常看到的UNSAFE.park(false,0L) 其实就是让线程立刻阻塞不参与线程调度。