LockSupport和Unsafe
LockSupport
LockSupport 的主要功能是提供线程一个"许可", 通过这个"许可"来控制线程的阻塞和恢复;
底层也是依赖于unsafe实现的
LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。LockSupport 提供park()和unpark()方法实现阻塞线程和解除线程阻塞,LockSupport和每个使用它的线程都有一个许可(permit)关联。permit相当于1,0的开关,默认是0,调用一次unpark就加1变成1,调用一次park会消费permit, 也就是将1变成0,同时park立即返回。再次调用park会变成block(因为permit为0了,会阻塞在这里,直到permit变为1), 这时调用unpark会把permit置为1。每个线程都有一个相关的permit, permit最多只有一个,重复调用unpark也不会积累。
unpark函数 可以先于 park 调用。比如线程B 调用 unpark函数,给线程A 发了一个“许可”,那么当线程A 调用 park 时,它发现已经有“许可”了,那么它会马上再继续运行。
LockSupport就是通过控制变量 _counter
来对线程阻塞唤醒进行控制的。原理有点类似于信号量机制。
- 当调用
park()
方法时,会将 _counter 置为 0,同时判断前值 < 1 说明前面被unpark
过,则直接退出,否则将使该线程阻塞。 - 当调用
unpark()
方法时,会将 _counter 置为 1,同时判断前值 < 1 会进行线程唤醒,否则直接退出。
形象的理解,线程阻塞需要消耗凭证(permit),这个凭证最多只有1个。当调用 park方法时,如果有凭证,则会直接消耗掉这个凭证然后正常退出;但是如果没有凭证,就必须阻塞等待凭证可用;而 unpark则相反,它会增加一个凭证,但凭证最多只能有1个。 - 为什么可以先唤醒线程后阻塞线程?
因为 unpark获得了一个凭证,之后调用 park因为有凭证消费,故不会阻塞。 - 为什么唤醒两次后阻塞两次会阻塞线程。
因为凭证的数量最多为 1,连续调用两次 unpark 和 调用一次 unpark 效果一样,只会增加一个凭证;而调用两次 park却需要消费两个凭证
LockSupport.park() 和 unpark() 和 object.wait() 和 notify() 很相似,那么它们有什么区别呢?
- 面向的主体不一样。LockSuport 主要是针对 Thread 进行阻塞处理,可以指定阻塞队列的目标对象,每次可以指定具体的线程唤醒。Object.wait() 是以对象为纬度,阻塞当前的线程和唤醒单个或所有线程。
- 实现机制不同。两者的阻塞队列并不交叉。也就是说
unpark
不会对wait
起作用,notify
也不会对park
起作用。object.notifyAll() 不能唤醒 LockSupport 的阻塞 Thread。 - wait和notify必须配合sychonozed关键字同时使用,不然会抛出异常,造成程序卡死的状态;
LockSupport 是 JDK 中用来实现线程阻塞和唤醒的工具。使用它可以在任何场合使线程阻塞,可以指定任何线程进行唤醒,并且不用担心阻塞和唤醒操作的顺序,但要注意连续多次唤醒的效果和一次唤醒是一样的。
中断分析
https://www.cnblogs.com/septemberFrost/p/12200755.html
总结
- interrupt会调用((JavaThread*)thread)->parker()->unpark(),将_counter设置为1,也即后面调用park不会阻塞
- sleep如果检测到中断会直接清除中断标志,并抛出异常。
- 因此两个Thread.interrupted()都返回false,且LockSupport.park()不会阻塞。
对于LockSupport.park()阻塞总结
如下两个条件任何一个成立,park()都不会阻塞:
- 中断标志位存在(wait、join、sleep或Thread.interrupted()都会清除中断标志位)
- _counter为1(之前调用了unpark或者interrupt)
Unsafe
java concurrent 包的基础是CAS, 而进行CAS操作的就是这个 Unsafe类.
Unsafe 类是Java中的保护类, 在外面包中使用通常通过反射获取 Unsafe类实例
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构