Java 并发的基石 LockSupport
Java juc 锁 About 833 wordsLockSupport
LockSupport
类使用了一种名为Permit
(许可)的概念来做到阻塞和唤醒线程的功能。
每个线程都有一个许可(Permit
)。
permit
只有两个值1
和0
,默认是0
。
park()
和unpark()
阻塞线程和解除阻塞线程
区别
wait/notify
wait
/notify
依赖于monitor
对象,必须在同一个同步块(锁同一个对象),否则会报java.lang.IllegalMonitorStateException
。如果notify
在wait
前面,则程序无法继续执行下去,一直等待被唤醒。
await/signal
condition
的await
和signal
同样依赖于Lock
对象,必须在lock
和unlock
中使用。如果await
在signal
前面,则程序无法继续执行下去,一直等待被唤醒。必须先等待后唤醒,线程才能被唤醒。
LuckSupport
wait
/notify
的改良版,无锁块要求。
unpark
可以在park
前执行。
底层原理
调用Unsafe
类中的native
方法。
park
方法:如果有凭证,则会直接消耗掉这个凭证后正常退出;如果无凭证,就必须阻塞等待凭证可用。
unpark
则相反,它会增加一个凭证,但凭证最多只能有1
个,累加无效。
使用park
和unpark
进行线程的阻塞和唤醒操作,park
和unpark
底层是借助系统层(C
语言)方法pthread_mutex
和pthread_cond
来实现的,通过pthread_cond_wait
函数可以对一个线程进行阻塞操作,在这之前,必须先获取pthread_mutex
,通过pthread_cond_signal
函数对一个线程进行唤醒操作。
面试题
为什么唤醒两次后阻塞两次,但最终还是会阻塞?
因为凭证的数量最多为1
,连续调用两次unpark
和调用一次unpark
效果一样,只会增加一个凭证;而调用两次park
却需要消费两个凭证,凭证不够,不能放行。
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓