volatile语义

2018-10-09  本文已影响9人  sunpy

介绍

我们经常看到volatile(易变的)修饰的变量,这个volatile是jvm提供的一种轻量级的同步手段,但是对于它自身使用场景,优缺点经常都是从每个片面的点去理解的,没有形成体系,打算总结下形式记忆体系。

volatile的特性

  1. 可见性
    就是保证变量对于所有线程都是可见的。对于volatile修饰的变量的读总能看到最后对该变量的写。
  2. 原子性
    就是保证任意单个volatile变量的读写操作具有原子性(但是volatile++这种复合操作不具备原子性)。
public class VolatileTest {

    public static volatile int i = 0;
    
    public static void iinc() {
        i++;
    }
    
    public static void main(String[] args) {    
        for (int t = 0 ; t < 30 ; t++) {
            new Thread(new Runnable() {

                public void run() {
                    for (int j = 0 ; j < 1000 ; j++) {
                        iinc();
                    }
                }
            }).start();
        }
        
        while (Thread.activeCount() > 1) {
            Thread.yield();
        }
        
        System.out.println(i);
    }
}
1.jpg

说明:应对这个情况我们想要原子性的int值可以采用AtomicInteger类来解决问题。

happens-before中的volatile

之前java内存模型讲到,java内存模型会使用重排序来优化程序,单线程的情况下,虽然数据有依赖性,但是在单线程中java内存模型会遵守as-if-serial语义来保证结果不会因为重排序改变。但是在多线程下就无法保证指令重排序了;但是volatile变量是禁止指令重排序优化的。happens-before性质定义了规则:对于volatile变量得写操作happens-before读操作

volatile内存语义

当写一个volatile变量时,java内存模型会把该线程对应的本地内存中的共享变量值刷新到主内存;store+write操作。
当读一个volatile变量时,java内存模型会把该线程对应的本地内存设置为无效,然后线程从主内存读取共享变量;read+load操作。

上一篇下一篇

猜你喜欢

热点阅读