zoukankan      html  css  js  c++  java
  • volatile关键字

    volatile是一个类型修饰符(type specifier).volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。JMM主要围绕在并发过程中如何处理并发原子性、可见性和有序性这三个特征来建立的,通过解决这三个问题,就可以解决缓存不一致的问题。而volatile跟可见性和有序性都有关。

    例如:

    对于代码:

    1 x=1;
    2 x=2;
    3 x=3;
    4 x=4;

     volatile的特性:

    1. volatile可见性:对一个volatile的读,总可以看到对这个变量最终的写;
    2. volatile原子性:volatile对单个读/写具有原子性(32位Long、Double),但是复合操作除外,例如:i++;
    3. jvm底层采用“内存屏障”来实现volatile语义。

    volatile的内存语义及实现:
      在JMM中,线程之间的通信采用共享内存来实现的。
    volatile内存语义是:

      • 当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值立即刷新到主内存中;
      • 当读一个volatile变量时,JMM会把该线程对应的本地内存设置为无效,直接从主内存中读取共享变量。

    正常编译,编译器会忽略前三条语句,如果键入volatile,则编译器逐一地进行编译并产生相应的机器代码(产生四条代码)。

    volatile的底层实现是通过插入内存屏障,但是对于编译器来说,发现一个最优布置来最小化插入内存屏障的总数几乎是不可能的,所以,JMM采用保守策略。如下:

    • 在每一个volatile写操作前面插入一个StoreStore屏障
    • 在每一个volatile写操作后面插入一个StoreLoad屏障
    • 在每一个volatile读操作后面插入一个LoadLoad屏障
    • 在每一个volatile读操作后面插入一个LoadStore屏障

    StoreStore屏障可以保证在volatile写之前,其前面的所有普通写操作都已经刷新到主内存中;
    StoreLoad屏障的作用是避免volatile写与后面可能有的volatile读/写操作重排序
    LoadLoad屏障用来禁止处理器把上面的volatile读与下面的普通读重排序
    LoadStore屏障用来禁止处理器把上面的volatile读与下面的普通写重排序

    1)一个参数既可以是const还可以是volatile吗?解释为什么。

    1)是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

    Volatile变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile变量的最新值。
    volatile变量不会像锁那样造成线程阻塞,因此也很少造成可伸缩性问题。在某些情况下,如果读操作远远大于写操作,volatile变量还可以提供优于锁的性能优势。
    正确使用 volatile 变量的条件
    您只能在有限的一些情形下使用 volatile变量替代锁。要使 volatile变量提供理想的线程安全,必须同时满足下面两个条件:
    ● 对变量的写操作不依赖于当前值。
    ● 该变量没有包含在具有其他变量的不变式中。
     
    使用 volatile变量的优点是简单,和性能,要原因是其简易性:在某些情形下,使用 volatile 变量要比使用相应的锁简单得多。使用 volatile变量次要原因是其性能:某些情况下,volatile 变量同步机制的性能要优于锁。
     
  • 相关阅读:
    指定盘符获取u盘PID、VID、序列号等信息
    禁用u盘再启用
    golang 使用编译选项-H=windowsgui后,仍然输出log到console
    c#实现"扫描检测硬件改动"
    哈希表
    Python 环境搭建
    Python 简介
    Python 基础教程
    7.1.2 定义改进的Sales_date类
    第七章 类
  • 原文地址:https://www.cnblogs.com/feichangnice/p/10654188.html
Copyright © 2011-2022 走看看