关于volatile关键字
来源:衡阳网站优化
在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关键字的更多相关文章
- Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...
- volatile关键字 学习记录2
public class VolatileTest2 implements Runnable{ volatile int resource = 0; public static void main(S ...
- volatile关键字 学习记录1
虽然已经工作了半年了...虽然一直是在做web开发....但是平时一直很少使用多线程..... 然后最近一直在看相关知识..所以就有了这篇文章 用例子来说明问题吧 public class Volat ...
- 【转】Java并发编程:volatile关键字解析
转自:http://www.importnew.com/18126.html#comment-487304 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备 ...
- 架构师养成记--4.volatile关键字
volatile修饰的变量可在多个线程间可见. 如下代码,在子线程运行期间主线程修改属性值并不对子线程产生影响,原因是子线程有自己独立的内存空间,其中有主内存中的变量副本. public class ...
- java中volatile关键字的含义
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...
- volatile关键字详解
本文系转载,原文链接:http://www.cnblogs.com/Chase/archive/2010/07/05/1771700.html,如有侵权,请联系我:534624117@qq.com 引 ...
- volatile关键字并不能作为线程计数器
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...
- volatile关键字及编译器指令乱序总结
本文简单介绍volatile关键字的使用,进而引出编译期间内存乱序的问题,并介绍了有效防止编译器内存乱序所带来的问题的解决方法,文中简单提了下CPU指令乱序的现象,但并没有深入讨论. 以下是我搭建的博 ...
- 也来说说C/C++里的volatile关键字
去年年底的样子,何登成写了一篇关于C/C++ volatile关键字的深度剖析blog(C/C++ Volatile关键词深度剖析).全文深入分析了volatile关键字的三个特性.这里不想就已有内容 ...
随机推荐
- svn报错:“Previous operation has not finished; run 'cleanup' if it was interrupted“
今天在eclipse上使用SVN:team - 显示资源历史记录 的时候报错. 方法是在本地磁盘项目目录上右键TortoiseSVN - Clean up 我的弹出的界面和下面一样,请勾选Break ...
- 八、SAP中使用MOVE来赋值
一.使用MOVE和使用等号的效果是等同的,代码如下: 二.效果如下:
- Assignment写作需要掌握的两种表达方式
在正式开始写Assignment之前都会进行文献检索和整理,选择适合Assignment选题的文献资料进行阅读和引用.对于文献中与自己的观点高度相关的参考资料要如何具体引用,而不造成抄袭或者增加文章的 ...
- 寒假day25
今天解决了部分数据爬取不下来的问题,同时进行了面试的准备
- MySQL表的几个简单查询语句
1. 创建数据库CREATE DATABASE database-name 2. 删除数据库drop database dbname 3. 创建新表create table tabname(co ...
- MySQL学习笔记——〇六SQLAlchemy框架
我们在前面所用的方法都是在可视化的视图软件或者terminal里直接写SQL语句来对数据库进行访问,这里我们大概讲一下一个新的框架——SQLAlchemy. OEM框架 OEM的概念 对象-关系映射( ...
- Dynamics CRM - 利用 JavaScript 打开指定 entity 的新建窗口并传递需要的参数
由于业务逻辑需要,需要从某个 Entity 的 Record 中弹出其他 Entity 的创建窗口,并将当前 Entity 中的某些值传递到新打开的窗口中,具体的 JS 代码如下: //定义一个参数对 ...
- 修复grub
进入命令行模式,#chroot /mnt/sysimage :切换根目录#grub2-install /dev/sda :安装grub2到第一硬盘#grub2-mkconfig -o /boot/gr ...
- java 面向对象概述, 函数解析
函数:class FunctionDemo { public static void main(String[] args) { /* int x = 4; System.out.println(x* ...
- 【WPF学习】第三十七章 触发器
WPF中有个主题,就是以声明方式扩展代码的功能.当使用样式.资源或数据绑定时,将发现即使不使用代码,也能完成不少工作. 触发器是另一个实现这种功能的例子.使用触发器,可自动完成简单的样式改变,而这通常 ...