原文链接:http://blog.csdn.net/zteny/article/details/54888629

一、简介

volatile是Java语言的关键字,用来修饰可变变量(即该变量不能被final修饰),且必须是至少类内可见。所以它是可以修饰带static的变量。这我自己下定义。

它是被设计用来修饰被不同线程访问和修改的变量。来自 百度百科

二、功能

volatile提供了一个高效的同步机制,她在某些情况下可以代替synchronized实现更轻量和高效的同步机制,同时也更为脆弱,更难于掌控。被volatile修饰的变量具有内存可见性,但不具有原子性。至于什么是可见性,前面已经做过简单介绍,接下来我们进一步来看什么是可见性。

1. 内存可见性

首先为什么会出现内存可见性问题呢? 
想完全理解这个问题,请自行阅读《深入理解计算机系统》吧!这里简单说一下,

每个线程都有它自己的线程上下文,包括栈、栈指针、程序计数器、通用目的寄存器和条件码。所有的运行在一个进程里的共享该进程的整个虚拟地址空间。——来自《深入理解计算机系统》

下面这个说法可能并不严谨,甚至是有误,但对我们理解这个问题有帮忙。 
如你所知,所有计算都发生CPU,然而它直接操作主存的效果比较远,不如CPU的缓存区,更远不如寄存器。其次,如上面所有的系统会为每个线程分配自己的线程上下文。在这两个大提前下,可能简化的理解为线程有自己的高速cache,即所有线程操作变量时,都不会直接操作主存。当发生cache miss时,从主存拷贝到cache,这些都是你懂的啦。跟所有的cache一样,都存在一致性的问题。

即是正常情况下什么时候发生cache冲刷回主存并不可控。 
不正常情况下,退出临界区时即刻强制更新主存。另一种情况,即我们要讨论的volatile。被volatile修饰的变量比较特殊,表示直接操作主存,不需要通过cache。直接要用时直接从主存取(注意取出来还是会把值放在自己的上下文,这点后面需要用到),用完写直接回主存。这就是内存可见性

2. 可不完全替代synchronized

之前整理synchronized的时候忘了讲synchronized怎么实现同步的,在这里顺便带出来吧。 
synchronized是通过临界区实现同步的,临界区的同步方式是同一个时间只有最多一个线程进入临界区,也就是说只能保证原临界区具有原子性。这是什么意思呢,先来看一下面例子吧。


void barfoo() {
new Thread(() -> {
for(int v=0; v<100; v++) bar();
}).start(); new Thread(() -> {
for(int v=0; v<100; v++) foo();
}).start();
}
} int v = 0;
void bar() {
final int t = v + 1;
v++;
try {
TimeUnit.MILLISECONDS.sleep(RandomUtils.nextInt(10));
} catch (InterruptedException e) { }
if(t != v)System.out.println("not match");
} synchronized void foo() {
final int t = v + 1;
v++;
try {
TimeUnit.MILLISECONDS.sleep(RandomUtils.nextInt(10));
} catch (InterruptedException e) { }
if(t != v)System.out.println("not match");
}

执行barfoo()的结果打印了not match。 
synchronized只是通过线程在离开临界区时会把线程上下文冲刷回主存,从而实现一致性,但对于变量v而言不具备原子性,更无法保证能够一致性。

volatile可部分替代synchronized,也就是说在特定条件或者场景下可以替代synchronized。上面我们提到过volatile具有内存可见性,但不具有原子性,而synchronized实际是上能够实现原子性的。这一点是volatile做不到的,也是这种场景下volatile无法代替synchronized。 
这一点就不举例了,主要知道什么是原子性和非原子性即可自行实验了。如:a += b就一个非原子性操作。

三、总结

  1. 简单的了解了volatile的用法;
  2. 进一步了解内存可见性和synchronized实现原理;
  3. volatile与synchronized的差异,以及可代替场景;
  4. volatile通过内存可见性实现同步,即线程A操作了被volatile修饰的变量之后,线程B立马可能读到线程A的修改结果。

我的另外一篇文章也有介绍:http://www.cnblogs.com/xuzekun/p/7426713.html

3.JUC之volatile的更多相关文章

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

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

  2. 【Java_多线程并发编程】JUC原子类——原子类中的volatile变量和CAS函数

    JUC中的原子类是依靠volatile变量和Unsafe类中的CAS函数实现的. 1. volatile变量的特性 内存可见性(当一个线程修改volatile变量的值后,另一个线程就可以实时看到此变量 ...

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

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

  4. JUC整理笔记二之聊聊volatile

    要想学好JUC,还得先了解 volatile 这个关键字.了解 volatile ,我们从一个例子开始吧. 本文不会很详细去说java内存模型,只是很简单地学习一下volatile 一个例子 pack ...

  5. JUC源码学习笔记4——原子类,CAS,Volatile内存屏障,缓存伪共享与UnSafe相关方法

    JUC源码学习笔记4--原子类,CAS,Volatile内存屏障,缓存伪共享与UnSafe相关方法 volatile的原理和内存屏障参考<Java并发编程的艺术> 原子类源码基于JDK8 ...

  6. JUC回顾之-volatile的原理和使用

    1.计算机内存模型的相关概念 计算机在执行程序时,每条指令都是在CPU中执行的,在指令的执行过程中,涉及到数据的读取和写入.由于程序在运行的过程中数据是放在"主存"中的, 由于数据 ...

  7. (一)juc线程高级特性——volatile / CAS算法 / ConcurrentHashMap

    1. volatile 关键字与内存可见性 原文地址: https://www.cnblogs.com/zjfjava/category/979088.html 内存可见性(Memory Visibi ...

  8. JUC(一):volatile关键字

    volatile是什么 ​ volatile是java虚拟机提供的轻量级同步机制,它包含三种特性: 保证可见性:只要主内存中变量做出修改,其余线程马上会感知到变量的修改. package com.ch ...

  9. JUC 并发编程--05, Volatile关键字特性: 可见性, 不保证原子性,禁止指令重排, 代码证明过程. CAS了解么 , ABA怎么解决, 手写自旋锁和死锁

    问: 了解volatile关键字么? 答: 他是java 的关键字, 保证可见性, 不保证原子性, 禁止指令重排 问: 你说的这三个特性, 能写代码证明么? 答: .... 问: 听说过 CAS么 他 ...

随机推荐

  1. opencv3.4.6 cmake

    Selecting Windows SDK version to target Windows 10.0.16299. Found PythonInterp: N:/Anaconda3/install ...

  2. DRBD UpToDate/DUnknown 故障恢复

    故障如下: root@drbd1:~# drbd-overview 0:data/0 StandAlone Primary/Unknown UpToDate/DUnknown /data/mysql ...

  3. Spring cloud微服务安全实战-6-5jwt改造之日志及错误处理(1)

    在代码里,我们没有认证或者授权的filter.认证和授权的工作现在基本上完全由Spring Security的过滤器接管了. 本节就来看下 如何在Spring Security的过滤器链上加入我们自己 ...

  4. Qt编写气体安全管理系统6-地图监控

    一.前言 地图监控主要是提供一个地图(可以是平面的也可以是立体彩色的,一般建议鸟瞰图,有3D感),然后设备在对应的地图上,可以切换地图来查看对应区域的设备,一般来说一个区域会有一个地图文件,设备在地图 ...

  5. Shenzhen Wanze Technology Co., Ltd.隐私协议

    本隐私权政策详细说明了Shenzhen Wanze Technology Co., Ltd.团队(“我们”或“我们的”)通过我们的应用程序和网站收集的信息,以及我们将如何使用这些信息. 1.我们不会通 ...

  6. ABAP DEMO ALVtree显示BOM层级

    展示效果: *&---------------------------------------------------------------------* *& Report YCX ...

  7. 知识点-Spark小节

    Spark处理字符串日期的max和min的方式Spark处理数据存储到Hive的方式Spark处理新增列的方式map和udf.functionsSpark处理行转列pivot的使用Python 3.5 ...

  8. centos docker 修改默认存储路径

    1.修改配置 将--graph /mnt/docker添加在docker.service文件中的ExecStart字段后面,其中/mnt/docker为你需要修改的存储目录 $ vim /usr/li ...

  9. scrapy,Twisted,pywin32安装

    安装包链接   百度云下载    https://pan.baidu.com/s/1V191nOtEDInxd_fkyi5siQ&shfl=sharepset Linux pip3 insta ...

  10. PHP中的重载技术

    PHP中的重载技术 通常面向对象语言的重载技术 其基本语法是这样的: 在一个类中,有多个同名的方法,每个方法的参数不同而已.这种现象就称为“重载”. 参数不同可以是:数量个数不同,或类型不同,或顺序不 ...