作者: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
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

java中关于volatile的理解疑问?的更多相关文章

  1. 你说一下对Java中的volatile的理解吧

    前言 volatile相关的知识其实自己一直都是有掌握的,能大概讲出一些知识,例如:它可以保证可见性:禁止指令重排.这两个特性张口就来,但要再往深了问,具体是如何实现这两个特性的,以及在什么场景下使用 ...

  2. 深入理解Java中的volatile关键字

    在再有人问你Java内存模型是什么,就把这篇文章发给他中我们曾经介绍过,Java语言为了解决并发编程中存在的原子性.可见性和有序性问题,提供了一系列和并发处理相关的关键字,比如synchronized ...

  3. Java中的volatile关键字的功能

    Java中的volatile关键字的功能 volatile是java中的一个类型修饰符.它是被设计用来修饰被不同线程访问和修改的变量.如果不加入volatile,基本上会导致这样的结果:要么无法编写多 ...

  4. java中线程同步的理解(非常通俗易懂)

    转载至:https://blog.csdn.net/u012179540/article/details/40685207 Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运 ...

  5. 一定要你明白Java中的volatile

    今天Tony来和大家聊聊Java中关键字volatile. 字节码 首先volatile int a = 3;和int a = 3;, 加不加volatile关键字,最终生成的字节码都一样的.有兴趣的 ...

  6. java中的volatile关键字

    java中的volatile关键字 一个变量被声明为volatile类型,表示这个变量可能随时被其他线程改变,所以不能把它cache到线程内存(如寄存器)中. 一般情况下volatile不能代替syn ...

  7. Java中线程同步的理解 - 其实应该叫做Java线程排队

    Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可 ...

  8. java中的Volatile关键字使用

    文章目录 什么时候使用volatile Happens-Before java中的Volatile关键字使用 在本文中,我们会介绍java中的一个关键字volatile. volatile的中文意思是 ...

  9. [读书笔记]java中的volatile关键词

    以下内容大多来自周志明的<深入理解Java虚拟机>. 当一个变量被volatile修饰后,它将具备两种特性: 1. 保证此变量对所有线程的可见性,这里的“可见性”是指当一条线程修改了这个变 ...

随机推荐

  1. C# 读写XML文件示例

    using System; using System.Collections.Generic; using System.Text; using System.Configuration; using ...

  2. sicily 1052. Candy Sharing Game

    Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description A number of students sit in a circle ...

  3. WA时查错点

    这篇文章旨在总结可能出错的原因,想到时随时会补充. 查看调试输出语句是否删除 查看数组是否清零 查看是否使用long long 查看是否有的常量应开LL(如1LL << (32) ) 查看 ...

  4. JVM 类加载过程、初始化、主动引用、被动引用、静态初始化块执行顺序

  5. ES6新数据结构Set让数组去重

    function unique(array){ return Array.from(new Set(array)); } var arr = ['aa','bb','cc','',1,0,'1',1, ...

  6. 前端读者 | 百度前端编码规范(CSS)

    本文来自:百度FEX 1 前言 CSS作为网页样式的描述语言,在百度一直有着广泛的应用.本文档的目标是使CSS代码风格保持一致,容易被理解和被维护. 虽然本文档是针对CSS设计的,但是在使用各种CSS ...

  7. npm更新包

    方法一手动跟新: 手动修改package.json中依赖包版本,执行npm install --force,强制从远程下载所有包更新本地包 方法二使用第三方插件: npm install -g npm ...

  8. Java之IO流的关闭

    1.在finally中关闭流: OutputStream out = null; try { out = new FileOutputStream(""); // ...操作流代码 ...

  9. python 正则匹配中文(unicode)(转)

    由于 需求原因,需要匹配 提取中文,大量google下,并没有我需要的.花了一个小时大概测试,此utf8中文通过,特留文.    参考: http://hi.baidu.com/nivrrex/blo ...

  10. Java浮点类型的格式化

    概述 基于Java,介绍将浮点类型小数进行格式化的方案. 正文 在Java中,用于格式化小数的类是java.text.DecimalFormat,比如你可以这样使用: double data = 33 ...