详细分析Java内存模型

  

详细分析Java内存模型的完整攻略

Java内存模型(Java Memory Model,JMM)是Java虚拟机(JVM)创造的一种抽象概念,用于规范Java程序在内存中的行为。因为Java程序是运行在虚拟机中,虚拟机又是运行在操作系统中,所以Java程序在内存中的表现是比较复杂的。Java内存模型对Java程序在内存中的访问和修改行为做了明确的规范,确保Java程序在不同的平台上能够一致地表现。

Java内存模型的基本概念

Java内存模型的基本概念包括:

  1. 主内存(Main Memory):Java程序访问的共享内存,JVM中所有线程都可以访问它。
  2. 工作内存(Working Memory):Java程序中每个线程独有的内存空间,线程执行时将主内存中的共享变量复制到工作内存中进行操作,操作完成后再写回主内存。
  3. 对象锁(Object Monitor):Java程序中一个对象可以用于同步的机制,线程可以通过竞争对象锁来获取对共享变量的访问权。

Java内存模型的规范

Java内存模型通过一些规范确保Java程序在内存中能够正确表现:

  1. 原子性:Java内存模型保证变量的读取和写入操作是原子的,即一个线程的写操作对于其他线程的读操作是同步可见的。
  2. 可见性:Java内存模型保证变量的写入操作对其他线程是可见的,即一个线程的写操作对于其他线程的读操作是同步可见的。
  3. 有序性:Java内存模型保证变量的读取和写入操作是有序的,即一个线程的写操作不会被重排序到对其他线程的读操作之后。

Java内存模型的示例

示例1:原子性

public class AtomicTest {
    private static volatile int count = 0;

    public static void main(String[] args) throws InterruptedException {
        for(int i=0;i<10;i++){
            new Thread(() -> {
                for(int j=0;j<1000;j++){
                    count++;
                }
            }).start();
        }
        Thread.sleep(3000);
        System.out.println("count:"+count); // 可能输出小于10000的数字
    }
}

在上面的代码示例中,定义了一个静态变量count,同时创建了10个线程对它进行操作,每个线程循环执行1000次count的自增操作。在程序最后,输出count变量的值。由于count变量的自增操作不是原子的,因此最终输出的count的值可能小于10000。

为了解决这个问题,可以使用JDK中提供的原子类,例如AtomicInteger。

示例2:可见性

public class VisibilityTest {
    private static volatile boolean flag = false;

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            while(!flag){
                // do something
            }
            System.out.println("Done!");
        }).start();

        Thread.sleep(1000);
        flag = true;
    }
}

在上面的代码示例中,定义了一个静态变量flag,并创建了一个线程不断循环执行直到flag变为true,然后输出Done!的信息。在主线程中,将flag变量赋值为true。

由于flag变量没有被volatile修饰,其写入操作在主线程的工作内存中完成,并没有及时写回主内存中,因此在另一个线程中flag变量的值可能为false,导致线程一直在循环执行。

为了解决这个问题,可以给flag变量添加volatile修饰符,确保写入操作能及时写回主内存中。

相关文章