简介
LockSupport 是 Java 并发工具包 java.util.concurrent 中的一个用于创建锁和其他同步类的基本线程阻塞原语。LockSupport 提供了 park() 和 unpark() 方法来停止和恢复线程。这些方法比低级的 wait/notify 和 notifyAll 方法更容易使用,并且与 java.util.concurrent 的高级同步工具更好地互相配合。
示例
在下面这个例子中,我们定义了两个线程。t1 打印数字,t2 打印字母。我们想要实现的效果是 t1 和 t2 交替打印,即输出结果为 “1A2B3C4D5E6F7G”。使用 LockSupport 的 park() 和 unpark() 方法,我们可以精确地控制线程的执行顺序,实现线程间的同步。
1 | import java.util.concurrent.locks.LockSupport; |
答疑
Q1:park 方法中的 blocker 的作用
这个 blocker 参数实际上是一个与该挂起操作关联的对象,这个对象会在调用 park() 方法后被设置到该线程,用于后续诊断和监控工具查看。它并不参与 park() 方法的工作逻辑,也不会影响挂起或者恢复线程的操作。这个对象通常是执行该操作的同步抽象(例如锁)。在调用 park 方法之后,可以使用 getBlocker(Thread) 方法来检索和清除该对象。
总的来说,blocker 对象主要是用于诊断和监控目的,它能帮助开发者或者工具更好地理解线程为何被挂起,以及哪个对象是造成线程挂起的原因。
Q2:LockSupport 相比于 Object.wait 和 Object.notify 的优势
LockSupport 相较于 Object.wait 和 Object.notify 提供了更高级、更安全、更灵活的线程同步机制,主要体现在以下几点:
- 无需在同步代码块里:调用
LockSupport的park()和unpark()方法不需要在synchronized代码块中,避免了不必要的同步,比较灵活。 - 中断影响:如果线程正在调用
park()阻塞,那么如果其他线程中断它,那么park()方法会返回,但不会抛出InterruptedException异常。 - 提供了 blocker 的概念:
LockSupport可以知道是因为什么原因导致线程被阻塞,这对于问题排查等方面会更有帮助。 unpark可以先于park调用:在Object.wait和Object.notify中,必须先执行wait再执行notify,否则notify的作用会丢失,而LockSupport则允许unpark先执行。
Q3: LockSupport.park()会释放锁资源吗
不会。LockSupport.park() 方法只是让当前线程进入等待状态,它不会释放任何线程可能持有的锁。这是因为,LockSupport.park() 是一个底层的线程阻塞工具,而不涉及 Java 的同步控制块(即 synchronized 关键字)或者 java.util.concurrent 包中的高级锁工具。
在使用 LockSupport.park() 时,需要特别注意这一点。如果一个线程在持有锁的情况下调用了 park() 方法并被阻塞,那么可能会导致其他试图获取该锁的线程也被阻塞,从而可能引发活跃性问题。