java并发编程(2)-volatile作用和实现原理

volatile作用
volatile用于保证量在并发环境中的可见性。它不需要切换线程状态所以一般情况下效率比synchronized要高很多。一般情况下在多核CPU环境中 为了提高计算效率,每个核心都会缓存变量到cpu核心本地的缓存中,cpu 计算过程会只更新本地缓存中的变量的值,待cpu比较空闲或其他恰当的实际会将本地缓存的变量值会写到系统内存。这样一来 如果一个线程修改了缓存中的值但是还没有 会写到 系统内存。那么其他线程是不会看到修改后的值的。这就是并发环境下的可见性问题。如果变量使用 volatile修饰,就可以解决可见性问题。即当cpu1修改了变量的值其他cpu会理科拿到更新后的值
除了可见性 对任意单个的volitale变量的读写具有原子性。 但是类似于 volatile++ 这种符合操作或者多个变量的操作 不具有原子性

原理:
1、对于volatile修饰的变量A,JVM会在为A赋值的代码后追加 lock指令。这个指令会告诉计算机,将更新后的值直接回写到系统主内存。
2、基于CPU硬件的缓存一致性协议,一旦变量A在主内存的值被更新那么其他缓存了变量A值的CPU会自动将缓存的值设置为无效。
如果再要读取A变量的值会直接从主内存中读取。

验证
下面代码验证了volitale对可见性的影响。

public class T {
    /* volatile */ static boolean running =true;
    void m1(){
        System.out.println("m start");
        while(running){
        // System.out.println("1");  // 如果加上这行代码 即使jdk8 下即使不用 volatile 也可以停止
        }
        System.out.println("m end");
    }
    public static void main(String[] args) {
        final T  t=new T();
        new Thread(){  // 传统线程写法    jdk8不加 valatile 只能打印 start  加了可以打印出end
            @Override
            public void run(){
                t.m1();
            }
        }.start();
     //   new Thread(t::m1,"T1").start();        //jdk8 λ表达式写法  不加 valatile 只能打印 start  加了可以打印出end
        try {
            Thread.currentThread().sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        t.running=false;
    }
}

测试结果:
在 jdk8 环境下 如果 running变量没有使用 volatile 关键字修饰 只能看到 start输出看不到 end 输出,而如果加了 volatile 关键字 就可以同时看到 start 和end 输出。原因就是上边分析的 如果不使用volatile 线程由于缓存了变量的值,所以一直从缓存中取。加了volatile 如果主内存的值被修改线程中缓存的值失效。只能从主内存中获取最新值。

jdk8环境下如果我们不使用 volitale ,而仅仅在循环中 增加一行 打印代码的话,线程T同样会停止。这是因为虽然线程T从缓存中获取变量的值,但是一旦CPU空闲,负载不太大的 时候 ,就会尝试和主内存的值进行同步,加了打印有了ioCPU 会相对空闲,所以会同步主内存的值。

在 jdk7 环境下, 无论 running变量有没有使用 volatile 关键字修饰 都可以输出start 和 end ,即即使没有volatile main线程修改了 running 的值 T1 线程也可以看到(应该是jdk8做了优化很显然一直从缓存读对于单线程来说效率更高)。运行结果如下:

m start
m end
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

catch that elf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值