详解volatile 关键字与内存可见性
先来看一个例子:
- public class VolatileTest {
- public static void main(String[] args) {
- ThreadDemo td = new ThreadDemo();
- new Thread(td).start();
- while (true) {
- if (td.isFlag()) {
- System.out.println("================");
- break;
- }
- }
- }
- }
- class ThreadDemo implements Runnable {
- private boolean flag = false;
- @Override
- public void run() {
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- }
- flag = true;
- System.out.println("falg=" + flag);
- }
- public boolean isFlag() {
- return flag;
- }
- public void setFlag(boolean flag) {
- this.flag = flag;
- }
- }
两个线程,一个改flag的值,主线程做判断,结果:

主线程的flag貌似还是false,按理通过Runnable创建的线程访问的应该是共享数据,那为什么会出现这种情况?这就涉及到内存可见性。
JVM会为每个线程分配一个独立缓存提高效率。上述例子中我们先在主存中开辟一块内存,如图:

那么这个两个线程,一个是读(主线程),一个是写(线程1),我们让线程1睡了200ms,说明,线程1先执行,每个线程都有一个独立的缓存,也就是说当线程1需要对主存的共享数值进行改变,它需要先把这个flag复制一份到缓存区中,

然后修改,将来再把这个值写回主存去,在写之前,主线程来了,它要读取现在在内存里面的值,现在是false,当然有一种情况,就是线程1在某个机会将flag=true写回去,


当时主线程用了while(true),这句话调用了系统底层代码,效率极高,高到主线程没有机会再次读取内存,这就是线程对共享数据操作的不可见。
内存可见性问题:当多个线程操作共享数据时,彼此不可见。
如何解决?同步锁。


但是用了锁,代表效率极低,但是我现在我不想加锁,但是有存在内存可见性的问题,我该怎么办?
关键字volatile:当多个线程进行操作共享操作时,可以保证内存中的数据可见。(内存栅栏,实时刷新)
我们可以认为它是直接在主存操作的,这个实时刷新的操作相比不加,性能略低,但是比加锁的效率显然高很多,低在哪?加了这关键字,JVM就不能进行指令重排序,无法优化代码执行。
- public class VolatileTest {
- public static void main(String[] args) {
- ThreadDemo td = new ThreadDemo();
- new Thread(td).start();
- while (true) {
- if (td.isFlag()) {
- System.out.println("================");
- break;
- }
- }
- }
- }
- class ThreadDemo implements Runnable {
- private volatile boolean flag = false;
- @Override
- public void run() {
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- }
- flag = true;
- System.out.println("falg=" + flag);
- }
- public boolean isFlag() {
- return flag;
- }
- public void setFlag(boolean flag) {
- this.flag = flag;
- }
- }

volatile相对synchronized是一种轻量级同步策略。但是注意:
- volatile不具备互斥性
- volatile不能保证变量的原子性
详解volatile 关键字与内存可见性的更多相关文章
- volatile关键字与内存可见性
前言 首先,我们使用多线程的目的在于提高程序的效率,但是如果使用不当,不仅不能提高效率,反而会使程序的性能更低,因为多线程涉及到线程之间的调度.CPU上下文的切换以及包括线程的创建.销毁和同步等等,开 ...
- volatile关键字与内存可见性&原子变量与CAS算法
1 .volatile 关键字:当多个线程进行操作共享数据时, 可以保证内存中的数据可见 2 .原子变量:jdk1.5后java.util.concurrent.atomic 包下提供常用的原子变量 ...
- 详解 volatile关键字 与 CAS算法
(请观看本人博文 -- <详解 多线程>) 目录 内存可见性问题 volatile关键字 CAS算法: 扩展 -- 乐观锁 与 悲观锁: 悲观锁: 乐观锁: 在讲解本篇博文的知识点之前,本 ...
- 【JUC系列第一篇】-Volatile关键字及内存可见性
作者:毕来生 微信:878799579 什么是JUC? JUC全称 java.util.concurrent 是在并发编程中很常用的实用工具类 2.Volatile关键字 1.如果一个变量被volat ...
- 详解volatile关键字和原子引用
本篇看一下Volatile关键字和原子引用. 上图就是JUC包结构,总共分成三块 (1)java.util.concurrent:并发包基础类,包括阻塞队列,线程池相关类,线程安全Map等. (2)j ...
- volatile关键字及内存可见性
先看一段代码: package com.java.juc; public class TestVolatile { public static void main(String[] args) { T ...
- java 轻量级同步volatile关键字简介与可见性有序性与synchronized区别 多线程中篇(十二)
概念 JMM规范解决了线程安全的问题,主要三个方面:原子性.可见性.有序性,借助于synchronized关键字体现,可以有效地保障线程安全(前提是你正确运用) 之前说过,这三个特性并不一定需要全部同 ...
- 【Java并发编程】6、volatile关键字解析&内存模型&并发编程中三概念
volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...
- volatile关键字解析&内存模型&并发编程中三概念
原文链接: http://www.cnblogs.com/dolphin0520/p/3920373.html volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java5之前,它是一个 ...
随机推荐
- qml demo分析(clocks-时钟)
一.效果展示 效果如图1所示,时钟列表支持鼠标左右拖动,带有黑色背景的是晚上时钟,无黑色背景的是白天时钟 二.源码分析 1.main.cpp文件中只包含了一个宏,该宏的具体解释请看qml 示例中的关键 ...
- 【Android Studio安装部署系列】十九、Android studio使用SVN
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 在AndroidStudio中开发版本控制,除了Git就是SVN,和Eclipse不同,Android Studio没有提供单独的插 ...
- springboot~mockMvc和asciidoctor生成基于TDD的API文档
API文档是前端与后端快速开发,减少沟通成本的必要条件,有一份完善的文档是很必要的,由通过测试来生成文档的好处就是:测试数据有了,测试返回结果有了,而且可以对这些字段进行说明,很清晰,在springb ...
- Springboot整合Elastic-Job
Elastic-Job是当当网的任务调度开源框架,有以下功能 分布式调度协调 弹性扩容缩容 失效转移 错过执行作业重触发 作业分片一致性,保证同一分片在分布式环境中仅一个执行实例 自诊断并修复分布式不 ...
- 目标检测 非极大值抑制(Non-Maximum Suppression,NMS)
非极大值抑制(Non-Maximum Suppression,NMS),顾名思义就是抑制不是极大值的元素,可以理解为局部最大搜索.也可以理解为只取置信度最高的一个识别结果. 举例:  如图所示,现在 ...
- 微信小程序开发06-一个业务页面的完成
前言 接上文:微信小程序开发05-日历组件的实现 github地址:https://github.com/yexiaochai/wxdemo 这里来说一说我们的理念,我们也学习小程序开发有一周多了,从 ...
- 如何在已有项目中引入FineUIMvc
FineUIMvc简介 FineUIMvc 是基于 jQuery 的专业 ASP.NET MVC 控件库,其前身是基于 WebForms 的开源控件库 FineUI(历时9年120多个版本).Fine ...
- .net 多线程 Thread ThreadPool Task
先准备一个耗时方法 /// <summary>/// 耗时方法/// </summary>/// <param name="name">< ...
- 从零开始学安全(四十)●上传文件MIME类型绕过漏洞防御
MIME检测原理 服务端MIME类型检测是通过检查http包的Content-Type字段中的值来判断上传文件是否合法的. php示例代码: if($_FILES['userfile']['type' ...
- Java异常实战——OutOfMemoryError
在Java虚拟机规范描述中,除了程序计数器外,虚拟机内存的其他几个运行区域都有发生 OOM 异常的可能.在这里,用代码验证各个运行时区域存储的内容并讨论该如何进行处理 Java堆溢出 Java 堆用于 ...