并发编程之 线程协作工具 LockSupport

并发编程之 线程协作工具 LockSupport_第1张图片
LockSupport

前言

在前面的文章中,我们介绍了并发工具中的4个,Samephore,CyclicBarrier,CountDownLatch,Exchanger,但是我们漏了一个,非常的好用的工具,楼主在这里必须加上。

LockSupport

LockSupport 是一个非常方便实用的线程阻塞工具,他可以在任意位置让线程阻塞。并且是静态的方法。是不是很心动?

LockSupport 的静态方法 park()可以阻塞当前线程,类似的还有 parkNanos(),parkUntil()等,他们实现了一个限时的等待。

同样的,有阻塞的方法,当然有唤醒的方法,什么呢?unpark(Thread) 方法。该方法可以将指定线程唤醒。

我们还是来一个例子吧,看看到底有多好用:


public class LockSupportInterruptDemo {

  static Object u = new Object();
  static ChangeObjectThread t1 = new ChangeObjectThread("t1");
  static ChangeObjectThread t2 = new ChangeObjectThread("t2");


  static class ChangeObjectThread extends Thread {

    public ChangeObjectThread(String name) {
      super.setName(name);
    }

    public void run() {
      synchronized (u) {
        System.out.println("in " + getName());
        // wait
        LockSupport.park();
        if (Thread.interrupted()) {
          System.err.println(getName() + "被中断了");
        }
      }
      System.out.println(getName() + "执行结束了");
    }
  }

  public static void main(String[] args) throws InterruptedException {
    t1.start();
    Thread.sleep(1000);
    t2.start();
    Thread.sleep(3000);

    t1.interrupt();
    // notify
    LockSupport.unpark(t2);
  }

}

执行结果:

并发编程之 线程协作工具 LockSupport_第2张图片

完全实现了 wait notify 的功能,但是,请注意,park 方法和 wait 方法相比,不需要获取某个对象的锁,也不会抛出 InterruptedException 异常,因此,你需要像我们的例子一样,使用静态方法进行判断。

如果你将 park 方法改成 park(this)/park(Thread),那么在打印 线程dump 信息的时候会打印阻塞对象的详细信息。

并发编程之 线程协作工具 LockSupport_第3张图片

该方法和 Lock 接口一样都是使用的 sun.misc.Unsafe 的 park 方法实现的阻塞。

还有一个需要注意的是:park 方法和 unpark 方法执行顺序不是那么的严格。比如我们在 Thread 类中提到的 suspend 方法 和resume 方法,如果顺序错误,将导致永远无法唤醒,但 park 方法和 unpark 方法则不会,我们测试一下,将 unpark 方法紧跟着 start 方法后面执行,那么也就是说,unpark 方法在 线程2 的park 方法之前执行,但结果相同。

并发编程之 线程协作工具 LockSupport_第4张图片

我们将 unpark 方法移动到了 start 方法后面,依然正确执行。

什么原因呢?这是因为 LockSupport 使用了类似信号量的机制。他为每一个线程准备了一个许可(默认不可用),如果许可能用,那么 park 函数会立即返回,并且消费这个许可(也就是将许可变为不可用),如果许可不可用,将会阻塞。而 unpark 方法则使得一个许可变为可用(但是和信号量不同的是,许可不能累加,你不可能拥有超过要给许可,他永远只有一个)。

下面是JDK文档:

并发编程之 线程协作工具 LockSupport_第5张图片
park
unpark

这个特定使得:即使 unpark 方法在 park 方法之前执行,他也可以使下一次的 park 操作立即返回。这也使上面的代码能正确执行的原因。

好了,到这里,LockSupport 就介绍完了,可以说,该方法可以替代 wait ,notify ,Condition 的 await ,signal 方法。注意,这里的 park 方法底层和 Lock 的底层实现是一致的。都是掉哟个 sun.misc.Unsafe。这个类可以说很牛逼。

good luck !!!!

你可能感兴趣的:(并发编程之 线程协作工具 LockSupport)