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

    一、什么是volatile关键字

      Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程。

      当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。

      volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。

      一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,

      那么就具备了两层语义: 1、保证多线程下的可见性   2、禁止进行指令重排序(即保证有序性)。

    二、内存模型的相关概念

    (1)不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的。

    (2)线程安全无非是要控制多个线程对某个资源的有序访问或修改。

        总结:java的内存模型多线程下,要解决两个主要的问题:可见性和有序性。

    (3)我们都知道计算机有高速缓存的存在,处理器并不是每次处理数据都是取内存的。

        JVM定义了自己的内存模型,屏蔽了底层平台内存管理细节。

    三、并发编程中的三个概念

      (1)原子性:

          只有简单的读取、赋值(而且必须是将数字赋值给某个变量,变量之间的相互赋值不是原子操作)才是原子操作。

      (2)可见性:

          多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

      (3)有序性:

          在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。

    五、使用volatile关键字的场景

      (1)使用valatile前后对比

      

      (2)valotile使用前提条件

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

          2、该变量没有包含在具有其他变量的不变式中

          简单来说:就是保证该操作是原子性操作

    六、volatile的原理和实现机制

      摘自《深入理解Java虚拟机》:

        “观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令”

        lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:

        (1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;

            即在执行到内存屏障这句指令时,在它前面的操作已经全部完成。

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

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

      

    七、synchronize与volatile的区别

     八、java中能创建volatile数组吗?

       能,java中可以创建volatile数组,不过只是一个指向数组的引用,

      而不是整个数组,如果改变引用指向的数组,将会受到volatile的保护,

      但是如果多个线程同时改变数组的元素,volatile 标示符就不能起到之前的保护作用了。

     九、volatile能使得一个非原子操作变成原子操作吗?

      一个典型的例子是在类中有一个 long 类型的成员变量。如果你知道该成员变量会被多个线程访问,如计数器、价格等,最好是将其设置为 volatile。

      为什么?因为 Java 中读取 long 类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位)。

      但是对一个 volatile 型的 long 或 double 变量的读写是原子。

     十、volatile 类型变量提供什么保证?

        volatile 变量提供顺序和可见性保证,

      例如,JVM 或者 JIT为了获得更好的性能会对语句重排序,但是 volatile 类型变量即使在没有同步块的情况下赋值也不会与其他语句重排序。

      volatile 提供 happens-before 的保证,确保一个线程的修改能对其他线程是可见的。

      某些情况下,volatile 还能提供原子性,如读 64 位数据类型,像 long 和 double 都不是原子的,但 volatile 类型的 double 和 long 就是原子的。

      

  • 相关阅读:
    QSPI
    温度标准
    minigui占用空间的情况
    引导页的展示
    Xcode6.0以后SVN的配置
    【转】iOS多线程编程技术之NSThread、Cocoa NSOperation、GCD
    SDWebImage最新使用
    OC设计模式
    Objective-c的@property 详解
    iOS开发时间戳与时间,时区的转换,汉字与UTF8,16进制的转换
  • 原文地址:https://www.cnblogs.com/fanhaiping/p/10075703.html
Copyright © 2011-2022 走看看