详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt202

Java内存模型:volatile是干什么用的

Volatile字段是用于线程间通讯的特殊字段。每次读volatile字段都会看到其它线程写入该字段的最新值;实际上,程序员之所以要定义volatile字段是因为在某些情况下由于缓存和重排序所看到的陈旧的变量值是不可接受的。编译器和运行时禁止在寄存器里面分配它们。它们还必须保证,在它们写好之后,它们被从缓冲区刷新到主存中,因此,它们立即能够对其他线程可见。相同地,在读取一个volatile字段之前,缓冲区必须失效,因为值是存在于主存中而不是本地处理器缓冲区。在重排序访问volatile变量的时候还有其他的限制。

在旧的内存模型下,访问volatile变量不能被重排序,但是,它们可能和访问非volatile变量一起被重排序。这破坏了volatile字段从一个线程到另外一个线程作为一个信号条件的手段。

在新的内存模型下,volatile变量仍然不能彼此重排序。和旧模型不同的时候,volatile周围的普通字段的也不再能够随便的重排序了。写入一个volatile字段和释放监视器有相同的内存影响,而且读取volatile字段和获取监视器也有相同的内存影响。事实上,因为新的内存模型在重排序volatile字段访问上面和其他字段(volatile或者非volatile)访问上面有了更严格的约束。当线程A写入一个volatile字段f的时候,如果线程B读取f的话 ,那么对线程A可见的任何东西都变得对线程B可见了。

如下例子展示了volatile字段应该如何使用:

class VolatileExample {
  int x = 0;
  volatile boolean v = false;
  public void writer() {
    x = 42;
    v = true;
  }

  public void reader() {
    if (v == true) {
      //uses x - guaranteed to see 42.
    }
  }
}
假设一个线程叫做“writer”,另外一个线程叫做“reader”。对变量v的写操作会等到变量x写入到内存之后,然后读线程就可以看见v的值。因此,如果reader线程看到了v的值为true,那么,它也保证能够看到在之前发生的写入42这个操作。而这在旧的内存模型中却未必是这样的。如果v不是volatile变量,那么,编译器可以在writer线程中重排序写入操作,那么reader线程中的读取x变量的操作可能会看到0。

实际上,volatile的语义已经被加强了,已经快达到同步的级别了。为了可见性的原因,每次读取和写入一个volatile字段已经像一个半同步操作了

重点注意:对两个线程来说,为了正确的设置happens-before关系,访问相同的volatile变量是很重要的。以下的结论是不正确的:当线程A写volatile字段f的时候,线程A可见的所有东西,在线程B读取volatile的字段g之后,变得对线程B可见了。释放操作和获取操作必须匹配(也就是在同一个volatile字段上面完成)。

Java内存模型:volatile详解的更多相关文章

  1. Java内存模型(JMM)详解

    在Java JVM系列文章中有朋友问为什么要JVM,Java虚拟机不是已经帮我们处理好了么?同样,学习Java内存模型也有同样的问题,为什么要学习Java内存模型.它们的答案是一致的:能够让我们更好的 ...

  2. Java并发关键字Volatile 详解

    Java并发关键字Volatile 详解 问题引出: 1.Volatile是什么? 2.Volatile有哪些特性? 3.Volatile每个特性的底层实现原理是什么? 相关内容补充: 缓存一致性协议 ...

  3. java内存模型-volatile

    volatile 的特性 当我们声明共享变量为 volatile 后,对这个变量的读/写将会很特别.理解 volatile 特性的一个好方法是:把对 volatile 变量的单个读/写,看成是使用同一 ...

  4. Java并发编程--Volatile详解

    摘要      Volatile是Java提供的一种弱同步机制,当一个变量被声明成volatile类型后编译器不会将该变量的操作与其他内存操作进行重排序.在某些场景下使用volatile代替锁可以减少 ...

  5. 深入理解Java内存模型 - volatile

    volatile的特性 当我们声明共享变量为volatile后,对这个变量的读/写将会很特别.理解volatile特性的一个好方法是:把对volatile变量的单个读/写,看成是使用同一个监视器锁对这 ...

  6. 深入理解Java内存模型——volatile

    volatile的特性 当我们声明共享变量为volatile后,对这个变量的读/写将会非常特别. 理解volatile特性的一个好方法是:把对volatile变量的单个读/写,看成是使用同一个监视器锁 ...

  7. 并发编程之 Java 内存模型 + volatile 关键字 + Happen-Before 规则

    前言 楼主这个标题其实有一种作死的味道,为什么呢,这三个东西其实可以分开为三篇文章来写,但是,楼主认为这三个东西又都是高度相关的,应当在一个知识点中.在一次学习中去理解这些东西.才能更好的理解 Jav ...

  8. Java内存模型-volatile的内存语义

    一 引言 听说在Java 5之前volatile关键字备受争议,所以本文也不讨论1.5版本之前的volatile.本文主要针对1.5后即JSR-133针对volatile做了强化后的了解. 二 vol ...

  9. Java内存泄露原因详解

    一.Java内存回收机制 不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址.Java中对象是采用new或者反射的方法创建的, 这些对象的创建都是在堆(He ...

  10. Java内存模型相关原则详解

    在<Java内存模型(JMM)详解>一文中我们已经讲到了Java内存模型的基本结构以及相关操作和规则.而Java内存模型又是围绕着在并发过程中如何处理原子性.可见性以及有序性这三个特征来构 ...

随机推荐

  1. 华为软件开发云对比Jenkins-JavaWeb项目持续部署方式

    一.前言:Jenkins介绍 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成和持续部署变成可能. 本文 ...

  2. ECMAscript6新特性之解构赋值

    在以前,我们要对变量赋值,只能直接指定值.比如:var a = 1;var b = 2;但是发现这种写法写起来有点麻烦,一点都不简洁,而在ECMAScript6中引入了一种新的概念,那就是" ...

  3. MongoDB入门命令

    查看所有数据库 > show dbs admin (empty) local 0.078GB > admin和管理相关, admin和local数据库不要轻易动 选择库 > use ...

  4. RedHat Enterprise Linu…

    RedHat Enterprise Linux 6.4 使用Centos 6 的yum 源问题 2015.04.09 一.问题描述 有时在使用RedHat 系统进行安装某些软件时,会出现如下提示: T ...

  5. Ubuntu下安装codeblocks

    ubuntu 16.04LTS 下Code::Blocks 16.01 安装 Code::Blocks 是一个开放源码的全功能的跨平台C/C++集成开发环境. Code::Blocks是开放源码软件. ...

  6. 求m区间内的最小值

    洛谷P1440 求m区间内的最小值 ............................................................................... 以上 ...

  7. TFS build server搭建,搭建自动化构建服务器

    TFS build 服务器的搭建主要步骤如下: 一:环境准备: 新建一台build服务器 安装Visual Studio.主要目的是: a. 生成Build脚本所需要的build命令:b.与TFS组合 ...

  8. css2--垂直对齐

    ## CSS2 vertical-align 垂直对齐     - baseline   默认值.基于基线对齐     - middle     位于同一行的非衬线字体小写字母的 1/2 处.不要为父 ...

  9. 前端开发之JavaScript篇

    一.JavaScript介绍  前端三剑客之JavaScript,简称js,可能是这三个里面最难的一个了.很早以前,市面上流通着三种js版本,为了统一,ECMA(欧洲计算机制造协会)定义了规范的版本, ...

  10. [ZYNQ-7]PS处理PL外部中断的简单实例的剖析 (参考米联miz702n)

    Zynq的ARM通过GIC中断控制器来接收核仲裁所有的中断.由于中断向量表只有4Bytes大小,仅仅正好存放一条跳转语句,因此当产生一个外部中断时,中断处理的大致过程:PC内容保存到LR_IRQ用于中 ...