并发编程笔记2--volatile底层实现原理

一、volatile应用

1、volatile的定义

定义:Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致性更新,线程应该通过排它锁确保单独获得这个变量。
volatile在某些情况下比锁更加方便,如果一个字段被声明成volatile,Java线程模型确保所有线程看到的这个变量都是一致的。当一个线程修改这个变量时,其他线程能读到这个修改后的值。

2、volatile如何保证可见性的

在有volatile修饰的共享变量进行写操作时,其汇编代码中会有Lock前缀。Lock前缀在多核处理器中会引发以下两种事情:

  1. 将当前处理器缓存行的数据写回到系统内存中
  2. 这个写操作会使在其他CPU里缓存了改地址的数据无效

为了提高处理速度,处理器不直接和内存交互,而是先将系统内存中的数据读到内部缓存(L1,L2,L3或其他)后再进行操作,但操作完不知道何时写到内存。也即是Java内存模型
WEBRESOURCE3fe646e2cba8bce7f5fb1bbeb099f488.png · 资源文件 · 语雀
当对非 volatile 变量进行读写的时候,每个线程先从内存拷贝变量到CPU缓存中。如果计算机有多个CPU,每个线程可能在不同的CPU上被处理,这意味着每个线程可以拷贝到不同的 CPU cache 中。
而声明变量是 volatile 的,JVM 保证了每次读变量都从内存中读,跳过 CPU cache 这一步,并且它会导致其他CPU中对应的缓存行无效。每次修改之后会立即回写到内存中。
禁止进行指令重排序。
volatile没办法保证对变量的操作的原子性。所以当进行复合操作时会出现问题,如i++问题
测试代码:

public class VolatileDemo {
    private volatile int i=0;
    private void test(){
        i++;
    }
    public static void main(String[] args) {
        final VolatileDemo test=new VolatileDemo();
        for (int i=0;i<10;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j=0;j<1000;j++){
                        test.test();
                    }
                }
            }).start();
        }
        //保证前面的线程都执行完
        while(Thread.activeCount()>2)
            Thread.yield();
        System.out.println(test.i);
    }
}
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值