在原子性、可见性、有序性中,volatile关键字主要在可见性中发挥作用。

volatile声明的变量对所有线程来说是可见的,就是说当变量的值发生改变的时候,其他线程可以立马发现这个变化。

public class Main {

private static boolean isRuning;

private static int number;

private static class ReaderThread extends Thread {

public void run() {

while (!isRuning) {

System.out.println(number);

}

}

}

public static void main(String[] args) throws InterruptedException {

new ReaderThread().start();

Thread.sleep(1000);

number = 42;

isRuning = true;

Thread.sleep(1000);

}

}

应该是由于编译器优化的存在,这里变量虽然没有被volatile修饰,但是仍然对其他线程可见。。。。。

那为啥Volatile修饰的变量i++却会有并发问题呢?

因为i++并不是原子操作,

i++是有两步操作的,比如 i=0; i++

1.读取i=0

2.计算i+1,然后赋值给i

那么可能存在2个线程同时读取到i=0,并计算出结果i=1然后赋值给I

那么就得不到预期结果i=2。

就是说虽然Volatile修饰的变量的变化可以被其他线程看到,但是如果同时去读这个变量,然后进行写操作,则仍会导致线程安全问题。

更底层的原因是什么呢?

首先要知道Volatile修饰的变量会做两件事(由lock指令完成):

1)将当前处理器缓存行的数据写回到系统内存。

2)写回内存的操作会使在其他 CPU 里缓存了该内存地址的额数据无效。

其他缓存会失效,不正好可以保证Volatile的原子性吗?

然而并不是,

比如有T1 T2两个线程进行i++操作。

当T1将变量加载到缓存,但是还没进行i++运算,T2呢已经加载完缓存并且已经执行完运算,那这个时候T1缓存里的值就该变成无效的了。

但是Volatile并不是让其他线程缓存无效以后就去重新加载主内存中的值,如果这时候T2缓存的值已经被放到寄存器并且cpu进行计算了,那即使缓存无效也不会影响T2将计算的值回写到主内存中。

关于cpu执行指令的过程可以参考https://blog.csdn.net/jizhu4873/article/details/84393905

当一个变量定义为 volatile 之后,将具备两种特性:

1.保证此变量对所有的线程的可见性,这里的“可见性”,如本文开头所述,当一个线程修改了这个变量的值,volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。但普通变量做不到这点,普通变量的值在线程间传递均需要通过主内存(详见:Java内存模型)来完成。

2.禁止指令重排序优化。有volatile修饰的变量,赋值后多执行了一个“load addl $0x0, (%esp)”操作,这个操作相当于一个内存屏障(指令重排序时不能把后面的指令重排序到内存屏障之前的位置),只有一个CPU访问内存时,并不需要内存屏障;(什么是指令重排序:是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理)。

volatile 变量的内存可见性是基于内存屏障(Memory Barrier)实现。

内存屏障则由lock指令实现

以上就是本次介绍的全部知识点内容,感谢大家对谷谷点程序的支持。

java violate 实例_Java的Volatile实例用法及讲解相关推荐

  1. java volatile实例_Java的Volatile实例用法及讲解

    Java的Volatile实例用法及讲解 发布时间:2020-10-03 12:01:58 来源:脚本之家 阅读:88 作者:konami 在原子性.可见性.有序性中,volatile关键字主要在可见 ...

  2. java $ 用法_Java的Volatile实例用法及讲解

    在原子性.可见性.有序性中,volatile关键字主要在可见性中发挥作用. volatile声明的变量对所有线程来说是可见的,就是说当变量的值发生改变的时候,其他线程可以立马发现这个变化. publi ...

  3. java中用法实例_java中Calendar类用法实例详解

    本文实例讲述了java中Calendar类用法.分享给大家供大家参考,具体如下: java中的Calendar在开发中经常被忽略,这篇博客总结一下这个类,对后面项目中使用时期的时候有帮助. Calen ...

  4. java printwriter实例_Java PrintWriter print(String)用法及代码示例

    Java中的PrintWriter类的print(String)方法用于在流上打印指定的String值.该字符串值用作参数. 用法: public void print(String StringVa ...

  5. java异常例子_java 异常的实例详解

    java 异常的实例详解 1.异常的定义:程序在运行时出现不正常情况. 异常的划分: Error:严重的问题,对于error一般不编写针对性的代码对其进行处理. Exception:非严重的问题,对于 ...

  6. java 反射 速度_Java反射获取实例的速度对比分析

    之前代码有一个逻辑,是在初始化时读取某个包下的所有class文件,放入到一个HashMap里.代码运行过程中,通过Key获取到对应class的全路径名,最后通过Class.forName(classN ...

  7. java 自定义正则表达式_java中正则表达式实例详解

    Java中正则表达式运用实例(参看java中正则表达式运用详解): 测试代码 package test; /** * 在String的matches()方法,split()方法中使用正则表达式. * ...

  8. java的继承实例_java继承(实例讲解一)

    Java继承(Java inheritance) Java继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类.这种技术使 ...

  9. java类初始化_Java的类/实例初始化过程

    昨天看到群里面有人分享了一道题目,我答错了,于是趁机了解了下Java的类/对象初始化过程: 程序的输出见文章最后 程序A主要考察的是 类实例初始化 .简单验证了下,类实例初始化过程如下:父类实例初始化 ...

  10. java 内存分配实例_java内存管理实例讲解

    一.java虚拟机运行时内存分配图 二.栈 堆 方法区简介 1.栈 1. 每个方法被调用都会创建一个栈帧(存储局部变量.操作数.方法出口等) 2. JVM为每个线程创建一个栈,用于存放该线程执行方法的 ...

最新文章

  1. POJ - 1904 King's Quest 强连通tanjar思想
  2. SpringBoot学习平台
  3. Spring MVC 到 Spring BOOT 的简化之路
  4. 将 VMware 最小化到系统托盘
  5. 基于发电厂知识问答库的检索式问答系统(python有代码)
  6. VS2017简单用法
  7. Python学习(五)列表的简单操作
  8. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol52]41所有的侧信道分析都是能量分析吗
  9. Citrix 实践中的问题及解决
  10. 末转变者登录服务器一直在排队,魔兽世界:国服神级服务器,排队持续两年,哈霍兰有何特别之处?...
  11. 计算机科学技术名家讲座许进,论高校计算机科学与技术课程中存在的问题与改革方向.pdf...
  12. 深圳荔枝公园没看到夜景(可能过节才有)
  13. Polar SI9000-PCB阻抗计算
  14. 【高等数学】第 5 讲 偏导数
  15. winserver2003打开ping
  16. 关于如何在win 10 中完成 ie 11 浏览器使用的解决方案(win7 升级 ie 11)
  17. 【EARLIER/EARLIEST函数】引用不存在的更早的行上下文 报错解决
  18. 矩阵树定理--luoguP4208 [JSOI2008]最小生成树计数
  19. AliExpress绑定万事达虚拟信用卡(Mastercard)测试实操教程
  20. matlab应用于体育彩票上,马尔科夫预测法在体育彩票“排列三”中的应用

热门文章

  1. 空悬指针和野指针(Dangling pointer and wild pointer)
  2. html中设置锚点定位的几种常见方法
  3. java中将一个字符数组赋值给另一个,两者同时变化
  4. 拓端tecdat|R语言分段线性回归分析预测车辆的制动距离
  5. 安卓studio没有java.xml_Android文件(Java和XML)被奇怪的XML替换
  6. 文献阅读 Fully Convolutional Networks for Semantic Segmentation
  7. model.train() model.eval()
  8. 修改mysql字符集后如何生效_修改MySQL字符集
  9. 10用户账户控制只有否_写了10 年的代码,收藏了这 20 个代码生成框架!
  10. Python:functools.cmp_to_key(func)使用