Java 并发的基石 LockSupport

Java juc About 833 words

LockSupport

LockSupport类使用了一种名为Permit(许可)的概念来做到阻塞和唤醒线程的功能。

每个线程都有一个许可(Permit)。

permit只有两个值10,默认是0

park()unpark()阻塞线程和解除阻塞线程

区别

wait/notify

wait/notify依赖于monitor对象,必须在同一个同步块(锁同一个对象),否则会报java.lang.IllegalMonitorStateException。如果notifywait前面,则程序无法继续执行下去,一直等待被唤醒。

await/signal

conditionawaitsignal同样依赖于Lock对象,必须在lockunlock中使用。如果awaitsignal前面,则程序无法继续执行下去,一直等待被唤醒。必须先等待后唤醒,线程才能被唤醒。

LuckSupport

wait/notify的改良版,无锁块要求。

unpark可以在park前执行。

底层原理

调用Unsafe类中的native方法。

park方法:如果有凭证,则会直接消耗掉这个凭证后正常退出;如果无凭证,就必须阻塞等待凭证可用。

unpark则相反,它会增加一个凭证,但凭证最多只能有1个,累加无效。

使用parkunpark进行线程的阻塞和唤醒操作,parkunpark底层是借助系统层(C语言)方法pthread_mutexpthread_cond来实现的,通过pthread_cond_wait函数可以对一个线程进行阻塞操作,在这之前,必须先获取pthread_mutex,通过pthread_cond_signal函数对一个线程进行唤醒操作。

面试题

为什么唤醒两次后阻塞两次,但最终还是会阻塞?

因为凭证的数量最多为1,连续调用两次unpark和调用一次unpark效果一样,只会增加一个凭证;而调用两次park却需要消费两个凭证,凭证不够,不能放行。

Views: 1,628 · Posted: 2021-04-10

————        END        ————

Give me a Star, Thanks:)

https://github.com/fendoudebb/LiteNote

扫描下方二维码关注公众号和小程序↓↓↓

扫描下方二维码关注公众号和小程序↓↓↓


Today On History
Browsing Refresh