关于JAVA中的JMM内存模型

Posted Keen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于JAVA中的JMM内存模型相关的知识,希望对你有一定的参考价值。

关于JAVA中的JMM内存模型

在Java中当多个线程操作同一个资源,由于某些原因当一个线程启动并获取资源后,若第二个线程队同一个资源进行了改动,在改动之前的线程并不会马上获取主存中的资源(CPU嗅探),这可能会造成阻塞.

JMM内存模型如下图:

为了解决这一问题,我们需要应用volatile关键字,volatile保证了资源的可见性、但不保证资源的原子性.

import java.util.concurrent.TimeUnit;

public class JMMDemo {
    // 不加 volatile 程序就会死循环!
    // 加 volatile 可以保证可见性
    private volatile static int num = 0;

    public static void main(String[] args) { // main

        new Thread(()->{ // 线程 1 对主内存的变化不知道的
            while (num==0){

            }
        }).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        num = 1;
        System.out.println(num);

    }
}

但是volatile关键字并不保证原子性,怎样保证资源的原子性呢?当然可以使用lock锁或者synchronized关键字,但这显然会降低程序的运行效率,在不考虑使用锁和同步代码块的情况下,我们可以使用JUC中提供的AtomicInteger类,详细代码如下:

import java.util.concurrent.atomic.AtomicInteger;

// volatile 不保证原子性
public class VDemo02 {

    // volatile 不保证原子性
    // 原子类的 Integer
    private volatile static AtomicInteger num = new AtomicInteger();

    public static void add(){
        // num++; // 不是一个原子性操作
        num.getAndIncrement(); // AtomicInteger + 1 方法, CAS
    }

    public static void main(String[] args) {

        //理论上num结果应该为 2 万
        for (int i = 1; i <= 20; i++) {
            new Thread(()->{
                for (int j = 0; j < 1000 ; j++) {
                    add();
                }
            }).start();
        }

        while (Thread.activeCount()>2){ // main  gc
            Thread.yield();
        }

        System.out.println(Thread.currentThread().getName() + " " + num);


    }
}

在代码的第11行中注释写到num++;其实并不是一个原子性操作,如果使用java的反编译命令查看字节码文件可

看出num++;的底层确实不是原子性的操作

至此,我们已经可以解决在多线程并行的情况下,主存与线程工作内存的一致性和可见性了,正如JMM内存模型要求的那样.

以上是关于关于JAVA中的JMM内存模型的主要内容,如果未能解决你的问题,请参考以下文章

Java内存模型(JMM)中的happens-before

来,了解一下Java内存模型(JMM)

终于有人把Java内存模型(JMM)说清楚了

Java内存模型(JMM)详解

Java——聊聊JUC中的Java内存模型(JMM)

Java——聊聊JUC中的Java内存模型(JMM)