来源:衡阳网站优化

在java核心卷1中对volatile关键字是这么描述的:

volatile关键字为实例域的同步访问提供了一种免锁机制。如果声明一个域为volatile,那么编译器和虚拟机就知道该域是可能被另一个线程并发更新的。

上述解释可以通过下面代码直观的描述:

public class VolatileAtomicSample {
static Logger logger = Logger.getLogger(VolatileAtomicSample.class); private static boolean initFlag = false; public static void refresh() {
logger.info("refresh data ......");
initFlag = true;
logger.info("refresh data success ......");
} public static void loadData() {
while (!initFlag) { }
logger.info("线程:" + Thread.currentThread().getName()
+ "当前线程嗅探到initFlag的状态的改变!");
} public static void main(String[] args) {
Thread threadA = new Thread(VolatileAtomicSample::loadData,"threadA");
threadA.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
} Thread threadB = new Thread(() -> {
refresh();
}, "threadB");
threadB.start();
}

上面的代码中线程B执行了refresh方法,貌似initFlag的值被改成了true,但是执行的结果仍然是:

refresh data ......

refresh data success ......

并没有打印:线程:threadA当前线程嗅探到initFlag的状态的改变!

如果将变量initFlag 用关键字 volatile 修饰,那么结果就是:

19/12/21 20:58:15 INFO volatile1.VolatileAtomicSample: refresh data ......
19/12/21 20:58:15 INFO volatile1.VolatileAtomicSample: refresh data success ......
19/12/21 20:58:15 INFO volatile1.VolatileAtomicSample: 线程:threadA当前线程嗅探到initFlag的状态的改变!

那么volatile的工作原理是什么,在底层是如何执行的。

可以通过一个图来描述:

主内存简称“主存” ,工作内存可以叫做线程的缓存。

线程A将initFlag先read出来,然后load到线程A的缓存中去,然后use就是交给代码来使用。

线程B也按线程A的方式来使用initFlag。

但是线程A,B之间是没有可见性的。所以,线程A读出来的initFlag=flase,是在线程A的工作内存中操作,线程B读出来的initFlag是在线程B的工作内存中操作,也是initFlag=flase,就算线程B将initFlag重新赋值成true,线程A也不知道,就出现了第一个结果。

如果将initFlag加上一个volatile修饰符,那么线程B的中将initFlag的值改成true,就会执行assign,将true从代码部分放回线程B的工作内存,然后线程B的工作内存回执行store,然后再将修改的数据write到主存中去,这个时候,各个线程回对总线做监听,这个总线可以理解成一条河,那么所有线程都从总线中知道initFlag的状态发生改变了。然后每个对initFlag操作的工作线程都停止自己的操作,重新从主存中获取最新的数据再操作。

所以就是下面的这个图:

volatile 的工作原理就是上面的样子。

画外音:图确实画的有点渣。

 

关于volatile关键字的更多相关文章

  1. Java并发编程:volatile关键字解析

    Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...

  2. volatile关键字 学习记录2

    public class VolatileTest2 implements Runnable{ volatile int resource = 0; public static void main(S ...

  3. volatile关键字 学习记录1

    虽然已经工作了半年了...虽然一直是在做web开发....但是平时一直很少使用多线程..... 然后最近一直在看相关知识..所以就有了这篇文章 用例子来说明问题吧 public class Volat ...

  4. 【转】Java并发编程:volatile关键字解析

    转自:http://www.importnew.com/18126.html#comment-487304 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备 ...

  5. 架构师养成记--4.volatile关键字

    volatile修饰的变量可在多个线程间可见. 如下代码,在子线程运行期间主线程修改属性值并不对子线程产生影响,原因是子线程有自己独立的内存空间,其中有主内存中的变量副本. public class ...

  6. java中volatile关键字的含义

    在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...

  7. volatile关键字详解

    本文系转载,原文链接:http://www.cnblogs.com/Chase/archive/2010/07/05/1771700.html,如有侵权,请联系我:534624117@qq.com 引 ...

  8. volatile关键字并不能作为线程计数器

    在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...

  9. volatile关键字及编译器指令乱序总结

    本文简单介绍volatile关键字的使用,进而引出编译期间内存乱序的问题,并介绍了有效防止编译器内存乱序所带来的问题的解决方法,文中简单提了下CPU指令乱序的现象,但并没有深入讨论. 以下是我搭建的博 ...

  10. 也来说说C/C++里的volatile关键字

    去年年底的样子,何登成写了一篇关于C/C++ volatile关键字的深度剖析blog(C/C++ Volatile关键词深度剖析).全文深入分析了volatile关键字的三个特性.这里不想就已有内容 ...

随机推荐

  1. hadoop yarn 实战错误汇总

    1.hadoop yarn 运行wordcount时执行完成,但是返回错误 错误信息如下: // :: INFO mapreduce.Job: Job job_1441395011668_0001 f ...

  2. 线性数据结构案例1 —— 单向链表中获取倒数k个节点

    一.介绍  先遍历整个链表获取链表长度length,然后通过 (length-index) 方式得到我们想要节点在链表中的位置. 二.代码 public Node findLastIndexNode( ...

  3. .NET CORE部署各种问题

    1.安装运行时以后,执行dotnet --version查看版本提示  丢失api-ms-win-crt-runtime-l1-1-0.dll, 当本地api-ms-win-crt-runtime-l ...

  4. 手把手教你用Python实现“坦克大战”,附详细代码!

    小时候玩的“坦克大战”,你还记得吗? ​ 满满的回忆 ! 今天,我们使用Python以及强大的第三方库来实现一个简单的坦克大战游戏. ​ 整体效果 环境依赖 python3.7 pygame1.9.6 ...

  5. 一小时搞定Eureka

    一.什么是Eureka Eureka是Netflix公司开源的产品,它是一种基于REST( Representational State Transfer )的服务,主要用于AWS云. Eureka提 ...

  6. python期末复习—列表

    列表:列表元素需用逗号分隔,放在方括号里,如:list=['Q',15];元素类型可以是数字,单个字符,字符串,列表.字符串和字符需要用单引号引起来. 访问列表:print(列表名[0])访问第一个元 ...

  7. springboot-jar

    预览 1.pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&quo ...

  8. [DDCTF 2019]homebrew event loop

    0x00 知识点 逻辑漏洞: 异步处理导致可以先调用增加钻石,再调用计算价钱的.也就是先货后款. eval函数存在注入,可以通过#注释,我们可以传入路由action:eval#;arg1#arg2#a ...

  9. HDU - 1068 Girls and Boys(二分匹配---最大独立集)

    题意:给出每个学生的标号及与其有缘分成为情侣的人的标号,求一个最大集合,集合中任意两个人都没有缘分成为情侣. 分析: 1.若两人有缘分,则可以连一条边,本题是求一个最大集合,集合中任意两点都不相连,即 ...

  10. opencv3。4安装出错

    https://www.samontab.com/web/2017/06/installing-opencv-3-2-0-with-contrib-modules-in-ubuntu-16-04-lt ...