zoukankan      html  css  js  c++  java
  • java中关于volatile的理解疑问?

    作者:xyzZ
    链接:https://www.zhihu.com/question/49656589/answer/117826278
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    .因为非原子性,volatile往往不能保证线程安全

    .因为非原子性,volatile往往不能保证线程安全

    .因为非原子性,volatile往往不能保证线程安全

    volatile 只能保证 “可见性”,不能保证 “原子性”。

    count++; 这条语句由3条指令组成:
    (1)将 count 的值从内存加载到 cpu 的某个寄存器r
    (2)将 寄存器r 的值 +1,结果存放在 寄存器s
    (3)将 寄存器s 中的值写回内存

    所以,如果有多个线程同时在执行 count++;,在某个线程执行完第(3)步之前,其它线程是看不到它的执行结果的。

    在没有 volatile 的时候,执行完 count++;,执行结果其实是写到CPU缓存中,没有马上写回到内存中,后续在某些情况下(比如CPU缓存不够用)再将CPU缓存中的值flush到内存。正因为没有马上写到内存,所以不能保证其它线程可以及时见到执行的结果。
    在有 volatile 的时候,执行完 count++;,执行结果写到CPU缓存中,并且同时写回到内存,因为已经写回内存了,所以可以保证其它线程马上看到执行的结果。
    但是,volatile 并没有保证原子性,在某个线程执行(1)(2)(3)的时候,volatile 并没有锁定 count 的值,也就是并不能阻塞其他线程也执行(1)(2)(3)。可能有两个线程同时执行(1),所以(2)计算出来一样的结果,然后(3)存回的也是同一个值。

    1.volatile不能保证原子性。简单说,java有所谓主内存区和线程栈,同一变量在主内存区和各个线程的栈都存在副本(一对多)。volatile提供的可见性,是说每个线程访问用volatile修饰的变量时,volatile都保证线程能从主存区加载到当前最新的值(反之,线程修改后同步到主存的值也要保证对其他线程的可见);

    2.java的volatile的语义其实不涉及cpu缓存。jvm本身是软件抽象,已经在操作系统之上;

    3.因为非原子性,volatile往往不能保证线程安全。如果只有简单读写操作如set i=2, get i, 可认为安全。i++就不行,它有一次读一次写;

    4、volatile被认为是比锁要轻,编程要简单。

    可以用volatile的地方:对一个变量,更新其值的时候不依赖于当前值,且该变量不会和其他一起构成一个不可变条件。


    作者:卓尔不浪得
    链接:https://www.zhihu.com/question/31990408/answer/54220910
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    『C#基础』C#读写TXT文档
    『ExtJS』给 Panel Items 中的 Grid 更新数据
    『Spring.NET』常见错误整理(持续更新)
    『WPF』Timer的使用
    『WPF』使用 [Annotation] 注释来定制数据/实体类
    『WPF』DataGrid的使用
    vbs修改注册表
    利用C#重启远程计算机
    sql server2000创建表和修改表
    存储过程得到某个表的所有字段信息
  • 原文地址:https://www.cnblogs.com/panxuejun/p/8622097.html
Copyright © 2011-2022 走看看