前言
关于 AQS 中的 Node.PROPAGATE
状态,源码中是这么说的:
PROPAGATE 状态表明下一次 acquireShared 应无条件传播。
releaseShared 方法应该传播到其他节点,该状态在 doReleaseShared 方法中设置(仅适用于头节点)以确保传播继续,即使其它操作已经介入。
但光看这些晦涩的文字,还是很难很好的理解它存在的意义,为什么要引入它呢?
通过查找资料发现,其实,PROPAGATE
状态的引入是为了解决 AQS 的一个 bug。
bug: https://bugs.openjdk.java.net/browse/JDK-6801020
fix: https://github.com/openjdk/jdk8u/commit/b63d6d68d93ebc34f8b4091a752eba86ff575fc2
这个 bug 是一个关于 Semaphore
的 case。
在 AQS 引入 PROPAGATE
状态前,并发调用 Semaphore
的 release
方法,某些情况下同步队列中排队的线程仍不会被唤醒。
这个 case 的完整代码如下:
import java.util.concurrent.Semaphore;
public class TestSemaphore {
/**
* Semaphore 初始状态为 0
*/
private static final Semaphore SEM = new Semaphore(0);
private static class Thread1 extends Thread {
@Override
public void run() {
// 获取 1 个许可,会阻塞等待其他线程释放许可,可被中断
SEM.acquireUninterruptibly();
}
}
private static class Thread2 extends Thread {
@Override
public void run() {
// 释放 1 个许可
SEM.release();
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10000000; i++) {
Thread t1 = new Thread1();
Thread t2 = new Thread1();
Thread t3 = new Thread2();
Thread t4 = new Thread2<