中心思想

使普通全局变量的写对其他线程立即可见(使用volatile有序性来传递)

内存屏障

先来一堆有必要的废话

  • LoadLoad屏障:对于这样的语句Load1; LoadLoad; Load2,在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。
  • StoreStore屏障:对于这样的语句Store1; StoreStore; Store2,在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。
  • LoadStore屏障:对于这样的语句Load1; LoadStore; Store2,在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。
  • StoreLoad屏障:对于这样的语句Store1; StoreLoad; Load2,在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。

Java内存模型允许编译器和处理器对指令重排序以提高运行性能,并且只会对不存在数据依赖性的指令重排序。

为了实现volatile的有序性内存语义(jdk5之后),编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。

  • 在每个volatile写操作的前面插入一个StoreStore屏障。
  • 在每个volatile写操作的后面插入一个StoreLoad屏障。
  • 在每个volatile读操作的前面插入一个LoadLoad屏障。
  • 在每个volatile读操作的后面插入一个LoadStore屏障

volatile写操作插入内存屏障后生成的指令序列如下图所示。

volatile读操作插入内存屏障后生成的指令序列如下图所示。

传递性 :如果操作A先行发生于操作B,操作B先行发生于操作C,那就可以得出操作A先行发生于操作C的结论。

相信大家对上面的内容很熟悉了,但是代表啥意思呢,估计你还是一头雾水。我们举个例子

int e = 0;
volatile f = 0;//thread 1
e = 1;    //操作 A
f = 1;    //操作 B//thread 2int j = f;   //操作 C
int k = e;    //操作 D

我们假设 thread 1 执行结束之后thread 2执行,由于f是volatile变量,那么可知B操作的写,对于C操作的读是可见的。那么可得B先发生与C,每个线程单独来看, A先发生与B, C先发生与D,最后我们再加上传递性可知。

A->B->C->D

至此我们可以得到普通变量e的的写入对于其他线程立即可见(注意变量f在其中起到的作用)

Reentrantlock 也借助了volatile的这个特性

总结一下有序性的含义

  1. 禁止指令重排
  2. volatile写会将线程工作缓存(cpu缓存)中的所有数据写入主存
  3. volatile读会将线程工作缓存(cpu缓存)中的所有数据失效,读的时候需要从主存中取。

测试代码

前面举的例子比较难测试出反例(对普通变量的写,不通过volatile的有序性保证,其他线程不是立即可见),所以写了下面的测试代码。

    static int a = 0;static volatile int b = 0;  //去掉volatile修饰会发生死循环,即变量a对于其他线程不是立即可见public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {while(a==0) {int c = b;}});thread.start();Thread.sleep(200);new Thread(() -> {a = 1;b = 1;}).start();thread.join();}

volatile有序性的真正作用相关推荐

  1. C语言 const、static、volatile等关键字的作用

    目录 前言 const static volatile extern 总结 前言 C语言里面有许多关键字,本文结合我自己的了解简单讲讲几个常用关键字的作用. const 问:const有什么用? 答: ...

  2. volatile是怎么保证可见性和有序性的,为什么无法保证原子性

    文章目录 1. JMM内存模型 2. 并发编程的三大特性 3. Volatile的原理分析 在了解volatile之前,先认识一下JMM内存模型和并发编程的三大特性! 1. JMM内存模型 Java内 ...

  3. Java中volatile的作用以及用法

    volatile让变量每次在使用的时候,都从主存中取.而不是从各个线程的"工作内存". volatile具有synchronized关键字的"可见性",但是没有 ...

  4. java中关键字volatile的作用(转载)

    转载:http://blog.csdn.net/orzorz/article/details/4319055 用在多线程,同步变量. 线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对 ...

  5. java 关键字volatile的作用

    用在多线程,同步变量. 线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B.只在某些动作时才进行A和B的同步.因此存在A和B不一致的情况.volatile就是用来 ...

  6. (免费领取名企Java面试题)volatile作用,指令重排相关

    (免费领取名企Java面试题)volatile作用,指令重排相关 Java是当下最热门的编程语言,越来越多的年轻人开始从事Java方面的工作,高就业率,高薪水的岗位,是吸引他们的原因.每个行业都有三六 ...

  7. volatile作用

    volatile 的主要作用有两点: - 保证变量的内存可见性 - 禁止指令重排序 前提知识了解 JMM 所有的共享变量都存储于主内存.这里所说的变量指的是实例变量和类变量,不包含局部变量,因为局部变 ...

  8. 对volatile的理解

    JMM 是什么 JMM(java内存模型 Java Memory Model)本身是一种抽象的概念,描述一组规则后规范通过这组规范定义了程序中各个变量(包括实例字段,静态变量和组成数组对象的元素)的访 ...

  9. 【并发编程】volatile简单使用

    Atomic 以更为轻量的方式实现原子性..本次我们学习 volatile 关键字,则是用来解决可见性.有序性问题. 简介 在 JDK1.2 之前,Java的内存模型实现总是从主存(即共享内存)读取变 ...

  10. null在java存在的意义何在,Java并发编程——volatile关键字

    一.volatile是什么 volatile是Java并发编程中重要的一个关键字,被比喻为"轻量级的synchronized",与synchronized不同的是,volatile ...

最新文章

  1. 【转】matlab函数_连通区域
  2. 跳出数据计算拯救人工智能之分布式逻辑
  3. php 写入文件 格式,在使用php写入文件时如何保证用户的单一
  4. winform list集合怎么 in过滤_python3基础04字典(dict)和集合(set)
  5. int类型存小数 mysql_MySQL面试题-数据类型
  6. javascript 解密_Javascript中的AES加密和Java中的解密
  7. Oracle-1 / Oracle及PlsqlDeveloper的设置
  8. 导弹如何自动追踪目标?这其实是个数学问题
  9. 【Java从0到架构师】SpringMVC - RESTful
  10. linux多媒体功能,Ubuntu 8.04中文强化版 多媒体功能更强大
  11. 适合有基础的Java实战项目——坦克大战 练手实战项目
  12. 【图像分割】基于粒子群算法实现图像聚类分割附matlab代码
  13. vue调用企业微信API详细过程
  14. 镭神C16上位机软件显示
  15. CHECK约束在表继承中的使用
  16. 使用poi解析Excel
  17. 企业私有网络构建与运维
  18. excel数据透视表数据排序及excel表格转成word表
  19. 【有利可图网】设计配色方案之紫色系篇
  20. 使用 Vuex + Vue.js 构建单页应用

热门文章

  1. QQ农场启示录之:偷菜成本核算
  2. 网工解惑?什么是路由器、交换机与防火墙,他们的区别与联系是什么?
  3. 用python祝福父亲节_python 计算 父亲节
  4. align latex 使用_LaTeX系列笔记(9)-数学模式下的间距及align等环境的实现
  5. 软件测试——课程感想
  6. 踩坑记6 vue3、生命周期钩子、vue-devtools beta
  7. Aras Innovator: AML包
  8. 1362:家庭问题(family)(并查集)
  9. 页面静态化的优点及缺点
  10. 超级简单的方法重装win10系统