Volatile 关键字 内存可见性
1、问题引入
实现线程:
public class ThreadDemo implements Runnable {private boolean flag = false;@Overridepublic void run(){flag = true;System.out.println("flag=" + flag);}public boolean isFlag(){return flag;}public void setFlag(boolean flag){this.flag = flag;} }
测试类:
public class VolatileTest {public static void main(String[] args){ThreadDemo threadDemo = new ThreadDemo();new Thread(threadDemo).start();while (true){if(threadDemo.isFlag()){System.out.println("----------------");break;}}} }
结果:flag=true,并且程序不会停止
结果分析:从结果中看到,线程threadDemo 将 flag 被修改为 ture 了,但是 while 循环中的 if 判断中没有进入(即 flag = false);主线程中的flag和threadDemo 中的flag值不一样。
内存可见性的问题:多个线程操作共享数据时,各个线程之间的数据不一致;
JVM会为每个线程分配一个独立的缓存用于提高效率。
(1)程序开始运行时主存中的flag=false;
(2)接着线程threadDemo会修改flag数据:threadDemo先从主存中获取到flag数据(false),然后在线程threadDemo中的缓存数据修改为true;
(3)在这个时候main线程来了,main线程从主存中读取到的flag=false;
(4)线程threadDemo将flag=true写入到主存中;
(5)while(true) 的执行效率特别高,以至于 main 线程没有机会从主存中读取数据;
解决内存可见性的问题:
1、增加同步锁,用 synchronized 进行同步,代码如下:
public class VolatileTest {public static void main(String[] args){ThreadDemo threadDemo = new ThreadDemo();new Thread(threadDemo).start();while (true){synchronized (threadDemo){if (threadDemo.isFlag()){System.out.println("----------------");break;}}}} }
以上代码存在的问题:增加同步锁解决了内存可见性的问题,但是效率特别低;
2、增加 volatile 关键字,修饰线程的共享数据,代码如下:
public class ThreadDemo implements Runnable {private volatile boolean flag = false;@Overridepublic void run(){flag = true;System.out.println("flag=" + flag);}public boolean isFlag(){return flag;}public void setFlag(boolean flag){this.flag = flag;} }
Volatile关键字不具备“互斥性”,Volatile不能保证“原子性”;
Java内存模型(Java Memory Model)描述了Java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节。
所有的变量都存储在主内存中。每个线程都有自己独立的工作内存,里面保存该线程使用到的变量的副本(主内存中该变量的一份拷贝),如图
两条规定:
- 线程对共享变量的所有操作都必须在自己的工作内存中进行,不能直接从主内存中读取
- 不同线程之间无法直接访问其他线程工作内存中的变量,线程间变量值的传递需要通过主内存来完成。
在这种模型下会存在一个现象,即缓存中的数据与主内存的数据并不是实时同步的,各CPU(或CPU核心)间缓存的数据也不是实时同步的。这导致在同一个时间点,各CPU所看到同一内存地址的数据的值可能是不一致。
volatile关键字:
能够保证volatile变量的可见性,不能保证volatile变量复合操作的原子
volatile如何实现内存的可见性:
深入来说:通过加入内存屏障和禁止重排序优化来实现的
在每个volatile写操作前插入StoreStore屏障,在写操作后插入StoreLoad屏障;
在每个volatile读操作前插入LoadLoad屏障,在读操作后插入LoadStore屏障;
通俗地讲:volatile变量在每次被线程访问时,都强迫从主内存中重读该变量的值,而当该变量发生变化时,又会强迫将最新的值刷新到主内存。这样任何时刻,不同的线程总能看到该变量的最新值。
线程写volatile变量的过程:
(1)改变线程工作内存中volatile变量副本的值
(2)将改变后的副本的值从工作内存刷新到主内存
线程读volatile变量的过程:
(2)从主内存中读取volatile变量的最新值到线程的工作内存中
(2)从工作内存中读取volatile变量的副本
参考链接:
https://www.cnblogs.com/amei0/p/8378625.html
转载于:https://www.cnblogs.com/yufeng218/p/10116595.html
Volatile 关键字 内存可见性相关推荐
- 24.volatile关键字的作用、volatile原理、可见性、内存屏障、volatile性能、transient
24.volatile关键字的作用 24.1.volatile原理 24.2.可见性 24.3.内存屏障 24.4.volatile性能 25.transient 24.volatile关键字的作用 ...
- 内存可见性和原子性:Synchronized和Volatile的比较
Java多线程之内存可见性和原子性:Synchronized和Volatile的比较 [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article ...
- 一文读懂Java内存模型(JMM)及volatile关键字
点赞再看,养成习惯,公众号搜一搜[一角钱技术]关注更多原创技术文章. 本文 GitHub org_hejianhui/JavaStudy 已收录,有我的系列文章. 前言 并发编程从操作系统底层工作的整 ...
- 全面理解Java内存模型(JMM)及volatile关键字
[版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/72772461 出自[zejian ...
- 爆赞,对 volatile 关键字讲解最好的一篇文章!
欢迎关注方志朋的博客,回复"666"获面试宝典 最近,在一篇文章中了解到了 volatile 关键字,在强烈的求知欲趋使下,我查阅了一些相关资料进行了学习,并将学习笔记记录如下,希 ...
- volatile关键字的作用、原理
在只有双重检查锁,没有volatile的懒加载单例模式中,由于指令重排序的问题,我确实不会拿到两个不同的单例了,但我会拿到"半个"单例. 而发挥神奇作用的volatile,可以当之 ...
- volatile关键字和AtomicInteger
在Java中,线程部分是一个重点,本篇文章说的JUC也是关于线程的.JUC就是java.util .concurrent工具包的简称.这是一个处理线程的工具包,JDK 1.5开始出现的.下面一起来看看 ...
- volatile关键字的作用-适用场景
volatile在Java并发编程中常用于保持内存可见性和防止指令重排序.内存可见性(Memory Visibility):所有线程都能看到共享内存的最新状态:防止指令重排:在基于偏序关系的Happe ...
- 【Java线程】深入理解Volatile关键字和使用
目录 背景 volatile原理 volatile特性 可见性 有序性 原子性 使用场景 背景 理解volatile底层原理之前,首先介绍关于缓存一致性协议的知识. 背景:计算机在执行程序时,每条指令 ...
最新文章
- JS 获取中英字符串字节长度
- mysql开发java心得_关于mysql 一些优化心得
- Ubuntu虚拟机磁盘扩容+VM虚拟机开机多出1分30秒的解决方案(终极教程)
- shell管道重定向程序的实现
- 批量修改Dell服务器远程管理卡iDRAC密码
- 核心编程第五版 配套代码_攻略Python的免费书单:走进编程,从这五本书开始...
- ping 丢包 网络摄像头_FIFA21 新加入网络连接监测功能
- OpenSSL版本号
- PowerDesigner设置code和name不联动的方法
- 消息队列 (1) mac安装RabbitMQ
- Dorado7之AjaxAction
- 苹果怎么用测试软件,iPhone 也能测量身高教你怎么用 iOS「测距仪」App
- flashfxp配置文件服务器同步,如何导出FlashFXP的站点配置文件
- Fuzzy set基本介绍(1)
- 从C端市场延伸至B端业务拓展,流利说深耕行业英语价值几何?
- 系统集成15真题解析
- 【解惑】杨中科说给弟弟的话
- 基于JSP的煤炭销售系统,源码下载
- Struts2类型转换的说明及案例分析
- 【IT简史】IBM(国际商业机器公司)