volatile

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

内存可见性:即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的

内存屏障(memory barrier):如果你的字段是volatile,Java内存模型将在写操作后插入一个写屏障指令,在读操作前插入一个读屏障指令。这意味着如果你对一个volatile字段进行写操作,你必须知道:1、一旦你完成写入,任何访问这个字段的线程将会得到最新的值。2、在你写入前,会保证所有之前发生的事已经发生,并且任何更新过的数据值也是可见的,因为内存屏障会把之前的写入值都刷新到缓存

 例如你让一个volatile的integer自增(i++),其实要分成3步:1)读取volatile变量值到local; 2)增加变量的值;3)把local的值写回,让其它的线程可见。这3步的jvm指令为

mov    0xc(%r10),%r8d ; Load
inc    %r8d           ; Increment
mov    %r8d,0xc(%r10) ; Store
lock addl $0x0,(%rsp) ; StoreLoad Barrier

   注意最后一步是内存屏障,写屏障指令

内存可见性

/**
 * volatile可以保证属性的可见性,一个线程修改了,另一个线程可以立刻知道该线程被修改了
 *
 */
public class VolatileTest {

    private static volatile  int INIT_VALUE = 0;

    private final static int MAX_LIMIT = 5;

    public static void main(String[] args) {
        new Thread(() -> {
            int localValue = INIT_VALUE;
            while (INIT_VALUE < MAX_LIMIT) {
                System.out.printf("Update the value to [%d]
", ++localValue);
                INIT_VALUE = localValue;
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "UPDATER").start();
        
        new Thread(() -> {
            while (INIT_VALUE <  3) {
                
            }
            System.out.println("结束循环了");
        }, "READER").start();

    }
}

内存屏障,防止重排序

class Singleton {
    private volatile static Singleton instance = null;
     
    private Singleton() {
         
    }
     
    public static Singleton getInstance() {
        if(instance==null) {
            synchronized (Singleton.class) {
                if(instance==null)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}

volatile不具备原子性

public class VolatileTest {
    
    private static volatile long value = 0;

    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(new LoopVolatile());
        t1.start();

        Thread t2 = new Thread(new LoopVolatile2());
        t2.start();

        t1.join();
        t2.join();
        System.out.println("final val is: " + value);  // final val is: 18585
    }

    private static class LoopVolatile implements Runnable {
        public void run() {
            long val = 0;
            while (val < 10000L) {
                value++;
                val++;
            }
        }
    }

    private static class LoopVolatile2 implements Runnable {
        public void run() {
            long val = 0;
            while (val < 10000L) {
                value++;
                val++;
            }
        }
    }
}

CPU高速缓存

JMM  java内存模型

原文地址:https://www.cnblogs.com/moris5013/p/10706547.html