美文网首页
volatile(gold_axe)

volatile(gold_axe)

作者: 胖达_4b7e | 来源:发表于2020-02-06 15:37 被阅读0次

用于修饰 要被多线程共享, 却不是final, 是可变 的 field
JIT编译器看到这个volatile 关键字形容了一个field, 就知道这是即会变化,又会被多线程共享的变量, 对它不能做一些优化, 比如不能被分配到处理器各自的寄存器上存储,
必须从主内存去那这个field的值

其能力是锁的子集, 比锁轻

原子性:对long/double 的 保证原子性(对其他类型的读写的原子性, java本来就有不用它来保证)

写volatile变量

之前有一个 释放屏障(Releas Barrier)

保证先后, 阻止重排

比如

volatile boolean ready = false;
public void writer() {
        dataA = 1;
        dataB = 10000L;
        dataC = "Content...";
        ready = true;
    }

ready是volatile修饰的 , 所以

ready = true;

这个 对它的赋值语句 之前的语句, 就必须确确实实在 对它的赋值语句 之前 执行了, 不能跑到它后面
跑到它后面 这种重排 是被 释放屏障(Releas Barrier) 阻止的

if (ready) {
            allISOK = (1 == dataA) && (10000L == dataB) && "Content...".equals(dataC);
            
        } 

↑这个allISOK肯定是true

之后有一个 存储屏障(Store Barrier)

存储屏障 作用是 冲刷高速缓存,
因此 对volatile变量的赋值 以后, 本线程的所有改过的共享变量, 都推送到其他cpu了, 其他cpu可以同步了
这是为了其他线程要读的话 能读到volatile变量的最新值, 顺带把其他共享变量也给冲刷了

读volatile变量

之前有一个加载屏障

加载屏障: 作用是 刷新 自己的高速缓存, 就是把自己的共享变量 更到和主内存一样的最新
这是为了 读volatile变量 会从主存拿最新的(其他共享顺便也变成最新了)

之后 有一个 获取屏障

就是 在读volatile变量 之后执行的代码, 就确实会在它之后, 不会被重排到前面

有序性:禁止重排

写volatile变量 之前 的操作, 不会被重排到 之后
读volatile变量 之后 的操作 , 不会被重排到之前


可见性: 刷新 和 冲刷

读前属性
写后冲刷


但是, 对引用变量内部的值, 可见性不能保证
比如对数组内部的元素
这点就不如

锁的内存屏障是这样


相关文章

网友评论

      本文标题:volatile(gold_axe)

      本文链接:https://www.haomeiwen.com/subject/eytuxhtx.html