volatile简介

java语言提供了一种稍弱的内存同步机制,即volatile变量。用来确保将变量的更新操作通知到其它线程,保证了新值能立即同步到主内存,以及每次使用前立即从内存刷新。当变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的。

volatile变量对所有线程可见,对volatile变量所有的写操作都能立即反应到其它的线程中,但是volatile并不能保证操作的原子性,因此volatile变量的运算并不是线程安全的。

并发编程中的三个概念

在并发编程中,我们通常会遇到以下三个问题:原子问题,可见性问题,有序性问题。

原子性:

即一个操作或多个操作要么全部执行并且执行过程中不能被任何操作打断,要么都不执行。只有简单的读取、赋值(而且必须是将数字赋值给某个变量,变量 之间的赋值不是原子操作)才是原子操作。java内存模型只保证了基本读取和赋值是原子操作,如果要实现更大范围操作的原子性,可以通过 synchronized和lock来实现。由于synchronized和lock能保证任一时刻只有一个线程执行该程序块,那么自然就不存在原子性问 题了,从而保证了原子性。

可见性:

可见性是指多个线程访问同一个变量时,一个线程修改了这个变量的值,其它线程能够立即看到修改的值。对于可见性,java提供了volatile关 键字来保证可见性。当一个共享变量被volatile修饰的时候,它会保证修改的值立即被更新到内存,当有其它线程需要读取时,它会去内存中去读新值。而 普通共享变量不能保证可见性。因为普通共享变量被修改后,什么时候被写入内存是不确定的。当其他线程去读取新值时,此时内存中可能还是原本的值,因此无法 保证可见性。

有序性:

即程序执行的顺序按照代码的先后顺序执行。在java内存模型中,允许编译器和处理器对执行进行重排,但是重排过程不会影响单线程程序的执行,却会 影响到多线程并发执行的正确性。在java中,可以通过volatile关键字来保证一定的有序性。另外可以通过synchronized和lock来保 证有序性。很显然,synchronized和lock保证了每个时刻只有一个线程执行同步代码,相当于是让线程执行同步代码,自然保证了有序性。

指令重排:

一般来说,处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行顺序同代码中的顺序一致,但是它会保证程序最终执 行结果和代码顺序执行的结果是一致的。如果两个语句之间没有数据依赖,那么可能会被重排。指令重排不会影响单个线程的执行,但是会影响到线程并发执行的正 确性。

在并发编程中,如果想要一个程序正确的执行,必须保证原子性、可见性以及有序性,只要有一个没有被保证,就有可能会导致程序运行不正确。

volatile关键字的两层含义

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层含义:

1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这个新值对其它线程来说是立即可见的。

2)禁止指令重排。

volatile关键字能够保证可见性,但是不能保证原子性。

volatile能禁止指令重排,所以volatile能在一定程度上保证有序性。

volatile关键字机制指令重排有两层意思:

1.当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经执行结束,并且结果已经对后面的修改可见,其后的操作一定还没有进行。

2.在进行指令优化时,不会对volatile变量进行重排。

从volatile关键字生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令。

lock前缀指令实际上相当于一个内存屏障。内存屏障会提供三个功能:

1)它确保指令重排时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障之后,即在执行到内存屏障这句指令时,在它前面的操作已经全部完成。

2)它会强制对缓存的修改操作立即写入内存。

3)如果是写操作,它会导致其他cpu中对应的缓存行无效。

使用volatile关键字的场景

synchronized关键字是防止多个线程同时执行一段代码,那么就会影响到程序的执行效率,而volatile关键字在某些情况下性能要优于 synchronized,但是要注意volatile关键字无法保证操作的原子性。通常来说,使用volatile必须具备以下两个条件。

1)对变量的写操作不依赖于当前值。

2)该变量没有包含在具有其它变量的不变式中。

意思就是保证操作是原子操作,才能保证使用volatile关键字的程序在并发时能够正确执行。

volatile简介的更多相关文章

  1. synchronized和volatile简介

    简介 volatile是一个变量修饰符,而synchronized是一个方法或块的修饰符.所以我们使用这两种关键字来指定三种简单的存取变量的方式. 2345678 int i1;int geti1() ...

  2. Java关键字:transient,strictfp和volatile简介

    关键字:transient 使用对象:字段 介绍:transient说明一个属性是临时的,不会被序列化. 当对象进行序列化(Serializable)过程时候,有一些属性的状态是瞬时的,这样的对象是无 ...

  3. volatile解析

    转载:http://www.importnew.com/17394.html 一.volatile简介: 在多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatil ...

  4. 5.彻底理解volatile

    1. volatile简介 在上一篇文章中我们深入理解了java关键字synchronized,我们知道在java中还有一大神器就是关键volatile,可以说是和synchronized各领风骚,其 ...

  5. Java并发编程,3分分钟深入分析volatile的实现原理

    volatile原理 volatile简介 Java内存模型告诉我们,各个线程会将共享变量从主内存中拷贝到工作内存,然后执行引擎会基于工作内存中的数据进行操作处理. 线程在工作内存进行操作后何时会写到 ...

  6. 彻底理解volatile,领悟其中奥妙

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  7. 让你彻底理解volatile,面试不再愁

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  8. java中的关键字volatile

    1.volatile简介 volatile作为java中的关键词之一,用以声明变量的值可能随时会被别的线程修改,使用volatile修饰的变量会强制将修改的值立即写入主存,主存中值的更新会使缓存中的值 ...

  9. 【C# 线程】 volatile 关键字和Volatile类、Thread.VolatileRead|Thread.VolatileWrite 详细 完整

    overview 同步基元分为用户模式和内核模式 用户模式:Iterlocked.Exchange(互锁).SpinLocked(自旋锁).易变构造(volatile关键字.volatile类.Thr ...

随机推荐

  1. 十六、Java基础---------集合框架之Set

    写在前面的话,这篇文章在昨天就写好了,今天打开的时候一不小心将第二天的文章粘贴到了这篇文章,很不幸的是除了标题之外依然面目全非,今天带着沉痛的心情再来写这篇文章! 上篇文章介绍了Collection体 ...

  2. Linux多节点互信配置

    SSH互信设置步骤:   1. 每个节点上分别生成自己的公钥和私钥   2. 将各节点的公钥文件汇总到一个总的认证文件authorized_keys中   3. 将这个包含了所有节点公钥的认证文件au ...

  3. Spark 1.1.0 编译(为了支持hbase 0.98.6)

    为了支持hbase0.98.6,需要重新编译spark 1. 下载spark 1.1.0源代码,以及 scala-2.10.4的bin包. 将环境变量 SCALA_HOME 设置为 scala-2.1 ...

  4. mysql5.6中 order by 多个字段排序问题

    今天用order by排序 后面跟了多个字段,如sql语句: SELECT a.id,a.loginname,a.address,u.id,u.`name`,u.address FROM admin_ ...

  5. [问题2014S06] 复旦高等代数II(13级)每周一题(第六教学周)

    [问题2014S06]  试用有理标准型理论证明13级高等代数I期末考试最后一题: 设 \(V\) 为数域 \(K\) 上的 \(n\) 维线性空间,  \(\varphi\) 为 \(V\) 上的线 ...

  6. Web页面速度测试工具

    开发框架的时间,想测试单例和多例下对性能的影响,找了下没有特别简单易用的测试工具. 估摸着搞了一个小工具. 针对.net Framework的2.0,3.5,4.0版本. WebHttpTest2.0 ...

  7. String,StringBuffer与StringBuilder的区别??[转]

    String 字符串常量StringBuffer 字符串变量(线程安全)StringBuilder 字符串变量(非线程安全) 简要的说, String 类型和 StringBuffer 类型的主要性能 ...

  8. Install-Package EntityFramework -version 5.0.0.0

    Install-Package EntityFramework -version 5.0.0.0

  9. iOS - Mac Apache WebDav 服务器配置

    前言 Apache 服务器: Web 服务器,可以支持各种脚本(PHP)的执行,目前世界上使用最为广泛的一种 Web 服务器 WebDav 服务器: 基于 http 协议的 "文件" ...

  10. codeforces 446A DZY Loves Sequences

    vjudge 上题目链接:codeforces 446A 大意是说最多可以修改数列中的一个数,求最长严格递增的连续子序列长度. 其实就是个 dp 的思想,想好思路后交上去没想到一直 wa 在第二个测试 ...