先看一段代码:

  

package com.java.juc;

public class TestVolatile {

    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;
public void run() {
try {
Thread.sleep(200);
flag = true;
System.out.println("flag= "+ isFlag());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* @return the flag
*/
public boolean isFlag() {
return flag;
}
/**
* @param flag the flag to set
*/
public void setFlag(boolean flag) {
this.flag = flag;
} }

运行这段代码,运行的结果只有:

  flag= true

这是由于 子线程在操作共享数据时,会将主存总的flag,复制一份到线程的缓存中进行操作,操作完成后会再将数据写到主存中,由于while(true)是一个运行效率非常高的一句代码,而且运行速度非常快,导致主线程再执行循环时没有机会从主存中读取到数据,导致flag的值是主线程最初读到的值,flag = false;

在共享变量上加一个volatile关键字,会解决这个问题

  

package com.java.juc;

public class TestVolatile {

    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;
public void run() {
try {
Thread.sleep(200);
flag = true;
System.out.println("flag= "+ isFlag());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* @return the flag
*/
public boolean isFlag() {
return flag;
}
/**
* @param flag the flag to set
*/
public void setFlag(boolean flag) {
this.flag = flag;
} }

----------------
flag= true

volatile 关键字的作用:当多个线程操作共享数据时,可以保证内存中的数据是可见的。

  可以使用内存再来解释,可以认为各个线程操作各自独立缓存中的数据是实时与主存进行同步的,可以理解为多个线程直接在主存中操作数据,而不是在各自的缓存中。

  加了volatile后性能还是比什么都不加要讲的,但是比锁的效率要高。

加了volatile之后效率会低在哪?

  实际上JVM底层有个优化,叫指令重排序,使用volatile修饰后就不能重排序了。

  

加锁的效率是最低的(使用synchronized关键字),同步锁会使线程每次从主存中读取数据,但是同步锁的效率很低。有多个线程来访问时先判断锁,如果被其他线程锁挡住,则线程会进入阻塞挂起状态,那得等到下次cpu再次分配任务,才能执行。

当然:volatile和synchronized还是不同的。volatile相较与synchronized是一种较为轻量级的同步策略。

注意:

  1. volatile 不具备 "互斥性"

  2. volatile 不能保证变量的 "原子性"

volatile关键字及内存可见性的更多相关文章

  1. volatile关键字与内存可见性

    前言 首先,我们使用多线程的目的在于提高程序的效率,但是如果使用不当,不仅不能提高效率,反而会使程序的性能更低,因为多线程涉及到线程之间的调度.CPU上下文的切换以及包括线程的创建.销毁和同步等等,开 ...

  2. volatile关键字与内存可见性&原子变量与CAS算法

    1 .volatile 关键字:当多个线程进行操作共享数据时, 可以保证内存中的数据可见 2 .原子变量:jdk1.5后java.util.concurrent.atomic 包下提供常用的原子变量 ...

  3. 详解volatile 关键字与内存可见性

    先来看一个例子: public class VolatileTest {            public static void main(String[] args) {           T ...

  4. 【JUC系列第一篇】-Volatile关键字及内存可见性

    作者:毕来生 微信:878799579 什么是JUC? JUC全称 java.util.concurrent 是在并发编程中很常用的实用工具类 2.Volatile关键字 1.如果一个变量被volat ...

  5. java 轻量级同步volatile关键字简介与可见性有序性与synchronized区别 多线程中篇(十二)

    概念 JMM规范解决了线程安全的问题,主要三个方面:原子性.可见性.有序性,借助于synchronized关键字体现,可以有效地保障线程安全(前提是你正确运用) 之前说过,这三个特性并不一定需要全部同 ...

  6. 【Java并发编程】6、volatile关键字解析&内存模型&并发编程中三概念

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

  7. volatile关键字解析&内存模型&并发编程中三概念

    原文链接: http://www.cnblogs.com/dolphin0520/p/3920373.html volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java5之前,它是一个 ...

  8. volotile关键字的内存可见性及重排序

    在理解volotile关键字的作用之前,先粗略解释下内存可见性与指令重排序. 1. 内存可见性 Java内存模型规定,对于多个线程共享的变量,存储在主内存当中,每个线程都有自己独立的工作内存,并且线程 ...

  9. Java并发机制(3)--volatile关键字与内存模型

    Java并发编程:volatile关键字解析及内存模型 个人整理自:博客园-海子-http://www.cnblogs.com/dolphin0520/p/3920373.html 1.线程内存模型: ...

随机推荐

  1. 使用Axure生成网站结构图

    使用Axure设计的各网站(产品)页面,生成网站(产品)结构图.这个对于了解网站整体结构很有帮助. 需要把它生成对应结构的网站结构图. 第一步:在“主页”上面新建一个和“主页”平级的页面,命名为“网站 ...

  2. Oracle索引表

    索引组织表(Index-Organized Table)是按B-树的结构来组织和存储数据的.与标准表中的数据时无序存放的不同,索引表中数据按主键值有序存储. 叶子节点中存放的是表的主键值与所有非主键值 ...

  3. sql两张表关联更新字段

    记录,推荐使用第三种,个人觉得比较好 --第一种写法,之前一直用,没有在意 UPDATE sr_t_TCodeUserReciveCfg SET fUserID=a.fUserID,fImportFl ...

  4. BFC与边距重叠详解

    1.什么是BFC? 在解释 BFC 是什么之前,需要先介绍 Box.Formatting Context的概念. Box: CSS布局的基本单位Box 是 CSS 布局的对象和基本单位, 直观点来说, ...

  5. DNS 缓存机制原理

    DNS 缓存机制原理 简单来说,一条域名的DNS记录会在本地有两种缓存:浏览器缓存和操作系统(OS)缓存.在浏览器中访问的时候,会优先访问浏览器缓存, 如果未命中则访问OS缓存,最后再访问DNS服务器 ...

  6. mongodb的原子性(Atomicity)和事物 (Transactions)

    在mongodb中,单个的写操作保持原子性是在单个的document 上. $isolated operator $isolated 一个写操作多个documents 的时候可以防止和其他进程交织,一 ...

  7. Python 字符串概念和操作

    # 字符串概念:由单个字符串组成的一个集合 # 普通字符串(非原始字符串) str = "abc" print(str) # abc # 原始字符串(前面加r) str = r&q ...

  8. 有些 where 条件会导致索引无效

    在查询中,WHERE 条件也是一个比较重要的因素,尽量少并且是合理的 where条件是徆重要的,尽量在多个条件的时候,把会提取尽量少数据量的条件放在前面,减少后一个 where 条件的查询时间.有些 ...

  9. 查找文件【TLCL】

    locate locate 执行快速的路径名数据库搜索,输出每个与指定子字符串相匹配的路径名. locate bin/zip locate 命令的数据库是updatedb命令创建的. find loc ...

  10. java基础(4)-数组(1)

    数组:存储同一种数据类型的多个元素的容器数组初始化: 元素类型[] 数组名 = new 元素类型[数组长度]int [] arr = new int[5] 元素类型[] 数组名 = new 元素类型[ ...