首页 > 其他分享 >Volatile关键字

Volatile关键字

时间:2024-08-20 23:15:06浏览次数:5  
标签:happens volatile 变量 关键字 线程 操作 Volatile before

背景

volatile关键字是并发编程中的一个比较重要的关键字。它能保证变量/对象在内存中的可见性,同时禁止指令重排序,避免了CPU或者编译器优化带来的可见性问题。
在并发编程中,volatile可以去修饰一个变量,或者是一个对象(比如单例模式中就使用了volatile去修饰单例对象)
举例说明

volatile int a = 100;
volatile SingleInstance instance;* 

什么是可见性?什么是可见性问题?

答: 可见性指的是一个共享变量被线程修改了以后,其他线程能立即看到变更后的变量值。因为线程是在各自的工作内存中执行数据的逻辑操作,并不会操作到主内存的变量值,一旦线程更新了变量的值,如果想要被可见,就必须立即再更新至主内存。所以,可见性问题就是指,A线程更新了变量的值,其他B线程操作变量的时候,没有得到这个变量变更后的新值,也就是A线程修改的值不可见。B线程使用旧值对变量进行更新操作,从而使得数据不一致。这个就是可见性问题!

如何解决变量可见性问题?

答:java中解决可见性问题的方案有很多。比如synchronzied, volatile, Lock锁,Atomic包下的原子类,JUC下的类。
synchronzied主要是保证同一时刻只能有一个线程操作某一个共享变量。避免多个线程同时访问一个共享变量带来的可见性问题。
volatile主要是会确保每个线程都能从主内存中读取该变量的最新值,而不是从自己的缓存中读取。本篇文章主要讲volatile的底层原理。

volatile的实现原理

volatile是通过内存屏障来禁止指令重排序,从而保证可见性的。
内存屏障有写屏障和读屏障(这些屏障实际上是一些硬件或者编译器级别的指令), volatile变量更新以后,会立即调用store指令,确保之前所有的写操作都会刷新到主内存中,避免写操作的重排序。读屏障确保读取volatile变量之前,会从主内存中读取最新的值。大多数处理器用的都是StoreLoad屏障。
StoreLoad相当于是一个全屏障,它会把处理器给变量赋值的指令存储到Store Buffer, 然后lock指令使到Store Buffer中的数据刷新到缓存行,同时使得其他CPU缓存了变量的缓存行失效。
所以说内存屏障底层其实还是调用了Lock指令。

happens before模型

这个JMM中的一些规范,主要是描述了两个操作指令的顺序关系。如果A操作和B操作存在happens-before的关系,那么意味着A操作的执行结果对B操作可见。
以下是一些Happens-before规则

Happens-before规则

  • 程序顺序原则
    在同一个线程中,如果x操作在Y操作之前,那么x happens before y,其实也是as-if-serial语义。
  • 传递性规则
    如果存在A happens before B; B happens before C, 那么必然会存在A happens before C 。
  • volatile变量规则
    指的是通过内存屏障来保障一个volatile修饰的变量的写操作一定happens before于其读操作。
  • 监视器锁规则
    一个线程对一个锁的释放操作一定happens before后续线程对该锁的加锁操作。
public void monitor() {
  synchronzied(this) {
  if(x == 0) {
    x = 10;
  }
}

如代码所示,当A线程执行逻辑之前,加上锁,执行结束后,会释放锁,此时A产生的结果对B一定是可见的。

  • start规则
    假如一个线程A调用子线程的start方法,那么线程A在调用start()方法之前的所有操作都happens-before线程B中的所有操作。
  • join规则
    首先join()的作用是等待某个子线程的执行结果。
    如果主线程main()执行了线程A的join()方法并且成功返回,那么线程A中的任意操作happens before 于main线程的join()方法返回之后的操作。

标签:happens,volatile,变量,关键字,线程,操作,Volatile,before
From: https://www.cnblogs.com/xyuanzi/p/18370414

相关文章

  • C++面试基础系列-volatile
    系列文章目录文章目录系列文章目录C++面试基础系列-volatile1.volatile核心规则2.C与C++中volatile区别2.1.C语言中的volatile2.2.C++中的volatile2.3.原子性和顺序2.4.易失性2.5.优化2.6.使用场景2.7.C++特有的特性2.8.C++20引入的变化(如果有)3.volatile常见面试问题4......
  • Sonarqube,标识代码中的username/password关键字,分别使用Tree.Kind.STRING_LITERAL 、T
    关于Tree.Kind.STRING_LITERAL、Tree.Kind.IDENTIFIER、Tree.Kind.TEXT_BLOCK等各个区别,请参考:Tree.Kind.STRING_LITERAL、Tree.Kind.IDENTIFIER、Tree.Kind.TEXT_BLOCK区别-yxchun-博客园(cnblogs.com) 1、使用 Tree.Kind.STRING_LITERAL packageorg.sonar.samp......
  • 【Linux】vim查找关键字
    在Linux下使用vim查找关键字命令非常简单。以下是一些常用的vim查找关键字命令:前向查找:按下“/”键,输入要查找的关键字,然后按下回车键。vim会自动定位到下一个匹配的关键字位置。向后查找:按下“?”键,输入要查找的关键字,然后按下回车键。vim会自动定位到上一个匹配的关键字位......
  • 关于volatile关键字为什么不能保证原子性(图文分析)
    文章目录概要多线程访问下数据的问题小结概要在网上的很多文章当中,都说到了volatile不可以保证原子性,对于这个关键字的定义解释的很清楚。volatile是Java中的一个关键字,用于修饰变量,它的主要作用是保证变量的可见性和禁止指令重排序。但是对于为什么这个关键字......
  • 今天来一期关键字大全
    1.asmasm(指令字符串):允许在C++程序中嵌入汇编代码。2.autoauto(自动,automatic)是存储类型标识符,表明变量"自动"具有本地范围,块范围的变量声明(如for循环体内的变量声明)默认为auto存储类型。3.boolbool(布尔)类型,C++中的基本数据结构,其值可选为true(真)或者false(假)。C++......
  • Java基础——面向对象编程高级(常见关键字)
    package:用于声明一个类或接口所属的包(即命名空间)语法格式:package顶层包名.子包名OrderController类属于包com.hxzs.order.controller一个源文件只能有一个声明包的package语句package语句作为Java源文件的第一条语句出现。若缺省该语句,则指定为无名包。包名,属于标识符,满......
  • 面试题:在Java中,volatile 关键字的作用是什么?它与 synchronized 关键字在实现线程同步
    面试题:在Java中,volatile 关键字的作用是什么?它与 synchronized 关键字在实现线程同步方面有何不同?请深入探讨其背后的原理和应用场景。更多答案在这里,手机或电脑浏览器就可以打开, 面霸宝典【全 拼音】.com 这里可以优化简历,模拟面试,企业项目源码,最新最全大厂高并......
  • Oracle数据库中,MINUS是一个关键字
    在Oracle数据库中,MINUS是一个关键字,用于执行两个SELECT语句的差集操作。MINUS操作返回在第一个SELECT语句中出现但不在第二个SELECT语句中出现的所有行。换句话说,它会从第一个查询结果中减去第二个查询结果,只保留在第一个查询结果中存在而第二个查询结果中不存在的记录。基本用法......
  • Java学习笔记5--关键字和保留字
    一、概念Java关键字(KeyWord):对Java的编译器有特殊的意义,他们用来表示一种数据类型或者表示程序的结构.保留字(ReserveWord):即它们在Java现有版本中没有特殊含义,以后版本可能会作为有特殊含义的词,或者该词虽然在Java中没有特殊含义,以后版本也不打算使用,但在其它语言中有特殊含义......
  • static关键字
    7.5static关键字目录7.5static关键字7.5.1static是什么7.5.2static修饰的成员变量是什么?有什么特点?7.5.3两种成员变量各自在什么情况下定义?7.5.4static修饰成员方法的基本用法7.5.6静态代码块7.5.1static是什么static是静态的意思,可以用来修饰成员变量、成员方法。......