从底层分析LockSupport原理机制
知识点
LockSupport的介绍
LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语。LockSupport实际上是调用了Unsafe类里的函数,归结到Unsafe里,只有两个函数,而仅仅两个简单的接口,就为上层提供了强大的同步原语,先来解析下两个函数是做什么的。
public native void unpark(Thread jthread);
public native void park(boolean isAbsolute, long time);
-
park:阻塞当前线程(Block current thread),字面理解park,就算占住,停车的时候不就把这个车位给占住了么?起这个名字还是很形象的。
-
isAbsolute参数是指明时间是否属于绝对。
-
time参数是指时间值
-
线程调用park函数则等待"许可"。
-
unpark: 使给定的线程停止阻塞(Unblock the given thread blocked)。
- thread参数是指对相应的线程进行解除阻塞。
线程调用unpark函数为线程提供"许可(permit)"。
-
这个有点像信号量,但是这个"许可"是不能叠加的,"许可"是一次性的。
-
比如,线程B连续调用了三次unpark函数,当线程A调用park函数就使用掉这个"许可",如果线程A再次调用park,则进入等待状态。
注意,unpark函数可以先于park调用。比如线程B调用unpark函数,给线程A发了一个"许可",那么当线程A调用park时,它发现已经有"许可"了,那么它会马上再继续运行。(此部分比wait/notify(notifyAll))要好很多。
park和unpark的灵活之处
unpark函数可以先于park调用,这个正是它们的灵活之处。
- 一个线程它有可能在别的线程unPark之前,或者之后,或者同时调用了park,那么因为park的特性,它可以不用担心自己的park的时序问题,否则,如果park必须要在unpark之前。
考虑一下,两个线程同步,要如何处理?
- 在Java5里是用wait/notify/notifyAll来同步的。wait/notify机制有个很蛋疼的地方是,比如线程B要用notify通知线程A,那么线程B要确保线程A已经在wait调用上等待了,否则线程A可能永远都在等待。
另外,是调用notify,还是notifyAll?
notify只会唤醒一个线程,如果错误地有两个线程在同一个对象上wait