关于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关键字的三个特性.这里不想就已有内容 ...
 
随机推荐
- 简单看看LongAccumulator
			
上篇博客我们看了AtomicLong和LongAdder的由来,但是有的时候我们想一下,LongAdder这个类也有点局限性,因为只能是每一次都+1,那有没有办法每次+2呢?或者每次乘以2?说得更抽象 ...
 - [题解] Luogu P5641 【CSGRound2】开拓者的卓识
			
这个柿子挺别致的......还有信仰膜数998244353 直接讲正解吧...... 首先发现这个柿子从上往下算好像不怎么行,我们从下往上看,(下面令\(Ans_r = sum_{k,1,r}\)). ...
 - 吴裕雄--天生自然TensorFlow2教程:测试(张量)- 实战
			
import tensorflow as tf from tensorflow import keras from tensorflow.keras import datasets import os ...
 - shell 疑难
			
#!/bin/bashBIN=`which $0`BIN=`dirname ${BIN}`BIN=`cd "$BIN"; pwd` #列出脚本所在目录全局路径
 - 深入分析解决Deepin 15环境变量修改问题,完成JAVA环境搭建
			
最近使用deepin配置JAVA环境时发现不论是修改/etc/profile还是 ~/.profile多次尝试后均无效,不得其解,最后通过官方论坛看到大神对deepin环境配置的解释,以及寻找到相关解 ...
 - A4纸表格打印
			
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
 - UML-快速的更新分析
			
1.目标 本章主要介绍需求和领域分析中的一些变更. 迭代1阶段:结束时,举行为期1-2天的简短的需求讨论会,内容是调查和详细编写更多需求+解决初始阶段反馈问题. 迭代2阶段:结束时,举行为期1-2天的 ...
 - 光纤卡网卡的区别以及HBA的常规定义-----引自百度百科
			
在讨论这个问题的时候,需要先说清楚一个问题:我们知道,在早期的SAN存储系统中,服务器与交换机的数据传输是通过光纤进行的,因为服务器是把SCSI指令传输到存储设备上,不能走普通LAN网的IP协议,所以 ...
 - Python 安装modules问题及import问题
			
>>>modules问题 在学习Python的数据可视化时,安装了matplotlib,在安装完成后还特意在终端测试了一下,结果显示能正常import 但是在sublime Text ...
 - linux的vi编辑器中如何查找内容(关键字)
			
按下”/“键,这时在状态栏(也就是屏幕左下脚)就出现了 “/” 然后输入你要查找的关键字敲回车就可以了. 找到相关文字以后: (1)按下小写n,向下查找 (2)按下大写N,向上查找