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扫描下方二维码关注公众号和小程序↓↓↓