JMM原子性及示例分析

JMM中保证了一些基本操作的原子性,例如读取和写入基本类型变量的操作。以下是一个示例说明JMM的原子性:

假设有两个线程t1和t2,它们同时对一个变量x进行自增操作。代码如下:

public class Main {
    public static int x = 0;
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000000; i++) {
                x++;
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 1000000; i++) {
                x++;
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(x);
    }
}

在这个示例中,两个线程t1和t2同时对变量x进行自增操作,每个线程自增1000000次。根据预期,程序应该输出2000000。然而,由于线程间的竞争关系,实际的输出结果可能会小于2000000。

如果没有JMM的原子性保证,线程t1和t2可能会同时读取x的值,然后都对其进行自增操作,导致x的值只增加1,而不是2。这就是典型的“竞态条件”(Race Condition)问题。

但是,由于JMM保证了对基本类型变量的读取和写入操作是原子的,所以线程t1和t2的自增操作会分别读取x的当前值,执行自增操作,然后将结果写回x。这样,即使t1和t2同时访问变量x,也不会发生竞态条件问题,程序的输出结果将会是正确的。

因此,JMM的原子性保证了对基本类型变量的读取和写入操作是原子的,从而避免了线程间的竞态条件问题,保证了程序在多线程环境下的正确性。