LockSupport是java.util.concurrent.locks包下的一个类
一、为什么需要LockSupport?
线程等待/通知机制中有三种方法实现:
wait()和notify()方法特点:
- 第一条中表示,在调用其方法时必须加锁后再调用,比如在synchronized代码块中调用。对于await()和signal()也是如此。
- 将notify放到wait前则程序无法执行,无法被唤醒。对于await()和signal()也是如此。
二、LockSupport
LockSupport位于java.util.concurrent.locks包下,有兴趣的可以直接去看源码,该类的方法并不是很多。LockSupprot是线程的阻塞原语,用来阻塞线程和唤醒线程。每个使用LockSupport的线程都会与一个许可关联,如果该许可可用,并且可在线程中使用,则调用park()将会立即返回,否则可能阻塞。如果许可尚不可用,则可以调用 unpark 使其可用。但是注意许可不可重入,也就是说只能调用一次park()方法,否则会一直阻塞。
public class LockSupportDemo { public static void main(String[] args) { Thread thread = new Thread(() -> { LockSupport.park(); System.out.println(Thread.currentThread().getName() + "被唤醒"); }); thread.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } LockSupport.unpark(thread); } }
- 这里只需要park、unpark,不再需要加锁,因为是许可证。
- park、unpark顺序颠倒也可以完成。先执行unpark,导致park形同虚设。
- 上面讲过许可证不可累加,所以代码中放入再多的unpark也没用,如果有两个park则程序无法运行。
- thread线程调用LockSupport.park()致使thread阻塞,当mian线程睡眠3秒结束后通过LockSupport.unpark(thread)方法唤醒thread线程,thread线程被唤醒执行后续操作。另外,还有一点值得关注的是,LockSupport.unpark(thread)可以指定线程对象唤醒指定的线程。