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

    volatile如何保持内存可见性

    Java变量读写:

    Java通过几种原子性操作完成工作内存和主内存交互

    1.lock:作用于主内存,把变量标识为线程独占状态

    2.unlock:作用于主内存,解除独占状态

    3.read:作用于主内存,把一个变量的值从主内存传输到线程的工作内存

    4.load:作用于工作内存,把read操作传过来的变量值放入工作内存的变量副本中

    5.use:作用于工作内存,把工作内存当中的一个变量值传给执行引擎

    6.assign:作用于工作内存,把一个从执行引擎接收到的值赋值给工作内存的变量

    7.store:作用于工作内存的变量,把工作内存的一个变量的值传送到主内存中

    8.write:作用于主内存的变量,把store操作传来的变量的值放入主内存的变量中

    volatile的特殊规则就是:

    read、load、use动作必须连续出现,assign、store、write动作必须连续出现

    所以,使用volatile可以保证:

    每次读取前必须先从主内存刷新最新的值,每次写入后必须立即同步回主内存当中

    即,volatile关键字修饰的变量看到的随时是自己的最新值,线程1中对变量v的最新修改,对线程2是可见的

    volatile如何防止指令重排序

    计算机在执行程序时,为了提高性能,编译器和处理器常常会对指令重排,一般分为以下三种:

    源代码 -> 编译器优化的重排 -> 指令并行的重排 -> 内存系统的重排 -> 最终执行指令

    单线程环境里面确保最终执行结果和代码顺序的结果一致

    处理器在进行重排序时,必须要考虑指令之间的数据依赖性

    多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性是无法确定的,结果无法预测。

      int x = 11;

      int y = 12;

      x = x + 5;

      y = x * x;

    按照正常单线程环境,执行顺序是 1 2 3 4

    但是在多线程环境下,可能出现以下的顺序:

    • 2 1 3 4
    • 1 3 2 4

    上述的过程就可以当做是指令的重排,即内部执行顺序,和我们的代码顺序不一样,但是指令重排也是有限制的,即不会出现下面的顺序

    • 4 3 2 1

    因为处理器在进行重排时候,必须考虑到指令之间的数据依赖性

    因为步骤 4:需要依赖于y的申明,以及x的申明,故因为存在数据依赖,无法首先执行

    多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性是无法确定的,结果无法预测,需要通过volatile来修饰,来保证线程安全性

    Volatile实现禁止指令重排优化,从而避免了多线程环境下程序出现乱序执行的现象

    首先了解一个概念,内存屏障(Memory Barrier)又称内存栅栏,是一个CPU指令,它的作用有两个:

    • 保证特定操作的顺序
    • 保证某些变量的内存可见性(利用该特性实现volatile的内存可见性)

    由于编译器和处理器都能执行指令重排的优化,如果在指令间插入一条Memory Barrier则会告诉编译器和CPU,不管什么指令都不能和这条Memory Barrier指令重排序,也就是说 通过插入内存屏障禁止在内存屏障前后的指令执行重排序优化

    内存屏障另外一个作用是刷新出各种CPU的缓存数,因此任何CPU上的线程都能读取到这些数据的最新版本

    线程安全获得保证

    工作内存与主内存同步延迟现象导致的可见性问题

    • 可通过synchronized或volatile关键字解决,他们都可以使一个线程修改后的变量立即对其它线程可见

    对于指令重排导致的可见性问题和有序性问题

    • 可以使用volatile关键字解决,因为volatile关键字的另一个作用就是禁止重排序优化
  • 相关阅读:
    Eclipse 读取config目录下文件
    cakephp 中Console / Shell 有什么优点?
    cakephp中使用 find('count')方法
    [转]using components in Cakephp 2+ Shell
    [转]Git for windows 下vim解决中文乱码的有关问题
    在Foxmail中添加阿里云企业邮箱账号
    Cakephp在Controller中显示sql语句
    java线程的基本概念
    mysql varchar到底能存多少字符。
    mysql 联合索引匹配原则
  • 原文地址:https://www.cnblogs.com/csuliujia/p/13031236.html
Copyright © 2011-2022 走看看