Skip to content

JSR 133 图 1

🏷️ JSR

今天写了段代码验证 JSR-133 中的第一个图例,确实如文件中描述的,出现了预想外的结果。

示例代码如下,使用CountDownLatch来尽量使两个线程中的处理同时开始。

java
package me.liujiajia.sample.multi.thread.sample;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;

public class MultiThreadSample001 {

    private static int A, B, r1, r2;

    public static void main(String[] args) throws InterruptedException {
        Set<String> resultSet = new HashSet<>();

        while (true) {
            A = 0;
            B = 0;
            r1 = 0;
            r2 = 0;

            CountDownLatch startCount = new CountDownLatch(2);
            CountDownLatch endCount = new CountDownLatch(2);

            Thread t1 = new Thread(() -> {
                try {
                    startCount.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                r2 = A;
                B = 1;

                endCount.countDown();
            });

            Thread t2 = new Thread(() -> {
                try {
                    startCount.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                r1 = B;
                A = 2;

                endCount.countDown();
            });

            t1.start();
            startCount.countDown();
            t2.start();
            startCount.countDown();

            endCount.await();

            String result = String.format("%d%d", r2, r1);
            if (!resultSet.contains(result)) {
                resultSet.add(result);
                System.out.println(String.format("r2 == %d, r1 == %d", r2, r1));
                if (resultSet.size() >= 4) {
                    break;
                }
            }
        }
    }
}

按照正常的理解,只会有三种结果,但运行的实际结果如下:

java
r2 == 0, r1 == 1
r2 == 2, r1 == 0
r2 == 0, r1 == 0
r2 == 2, r1 == 1

出现第四种情况的原因是指令可能被重排为下图中右侧的形式,此时就可能会出现上面的第四种情况。

将变量定义为volatile后,将只可能出现前三种情况:

java
private volatile int A, B, r1, r2;
java
r2 == 0, r1 == 1
r2 == 2, r1 == 0
r2 == 0, r1 == 0