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 @ 2020-04-16 21:12  牛有肉  阅读(2360)  评论(0编辑  收藏  举报