深入理解Volatile

Volatile的原理:volatile变量修饰的共享变量进行写操作时会在汇编代码前加上lock前缀,lock前缀的指令在多核处理器下会引发两件事情:

  • 将当前处理器缓存行的数据写回到系统内存
  • 该写回内存的操作会使在其他CPU里缓存了该内存地址的额数据无效
Volatile特性之一:保证线程之间的可见性

保证变量在线程之间的可见性。可见性的保证是基于CPU的内存屏障指令,被JSR-133抽象为happens-before原则。

Volatile特性之二:禁止指令重排

阻止编译时和运行时的指令重排。编译时JVM编译器遵循内存屏障的约束,运行时依靠CPU屏障指令来阻止重排。

Volatile特性之三:不保证原子性
public class Test {
    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        for(int i = 0; i < 6666; ++i){
            new Thread(() -> {
                try {
                    mythread.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, "test").start();
        }
        System.out.println("Thread-" + Thread.currentThread().getName() +
                " current num value:" + mythread.num);
    }
}

class Mythread{
    volatile int num = 0;

    public void increment(){
        ++num;
    }
}

在这里插入图片描述
可以看到,循环执行了6666次,但最后的结果为6663,说明在程序运行过程中出

现了重复的情况。

解决方案

  1. 使用JUC中的Atomic类(之后会专门写一篇学习笔记进行阐述)
  2. 使用synchronized关键字修饰(不推荐)

在这里插入图片描述

  1. 主内存(Main Memory)
    主内存可以简单理解为计算机当中的内存,但又不完全等同。主内存被所有的线程所共享,对于一个共享变量(比如静态变量,或是堆内存中的实例)来说,主内存当中存储了它的“本尊”。
  2. 工作内存(Working Memory)
    工作内存可以简单理解为计算机当中的CPU高速缓存,但又不完全等同。每一个线程拥有自己的工作内存,对于一个共享变量来说,工作内存当中存储了它的“副本”。

线程对共享变量的所有操作都必须在工作内存进行,不能直接读写主内存中的变量。不同线程之间也无法访问彼此的工作内存,变量值的传递只能通过主内存来进行。

什么时候适合用volatile呢?

  1. 运行结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值。
  2. 变量不需要与其他的状态变量共同参与不变约束
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值