park/unpark 阻塞与唤醒线程

 

  使用 JAVA 进行多道编程时,除了通过 wait/notify 对线程进行阻塞/唤醒外,我们还可以使用 LockSupport 工具类来阻塞和唤醒线程。

  比如:

复制代码
        Thread threadTest = new Thread(
                () -> {
                    System.out.println("thread start!");
                    LockSupport.park();
                    System.out.println("thread weakup!");
                }
        );
        threadTest.start();
        Thread.sleep(100);
        System.out.println(" from main thread");
        LockSupport.unpark(threadTest);
复制代码

  执行结果:

   与 wait/notify 相比,park/unpark 方法更贴近操作系统层面的阻塞与唤醒线程。park/unpark 没有基于对象锁的上层判断逻辑,更直接的通过系统调用来操作线程,当然在系统调用之上还是做了一些小封装。与 wait/notify 相比:

  1. park不需要获取某个对象的锁
  2. 因为中断的时候park不会抛出InterruptedException异常,所以需要在park之后自行判断中断状态,然后做额外的处理。就像 sleep ,notify 唤醒后,jvm 会帮助我们检查一次是否有 interrupt 信号,其原理之前做过解析 https://www.cnblogs.com/niuyourou/p/12392942.html ,将检查 interrupt 信号的逻辑放在阻塞线程的逻辑之后,一旦被唤醒,首先执行检查 interrupt 信号的逻辑,检查完后退出 sleep/wait 方法,程序继续向下执行。而 park / unpark 并没有提供类似的机制,如果需要我们应自己在 park 方法后加入检查 interrupt 信号的逻辑。
  3. 想想happen-before原则中有一条,同一个锁的unlock操作happen-before此锁的lock操作。park/unpark 并没有涉及到锁操作,但我们确实有保证在一对操作中, park 发生在 unpark 之前的需求,否则可能会造成程序的死锁。关于这点 park/unpark 通过为线程附加状态位满足了我们的需求:unpark调用时,如果当前线程还未进入park,则将许可设置为true;park调用时,判断许可是否为true,如果是true,则 park 不阻塞线程,程序继续往下执行;如果是false,则阻塞线程。所以只要我们的 park/unpark 成对出现,无论执行顺序如何,都不会因此造成死锁。

 

posted @   牛有肉  阅读(2370)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示