gpt4 book ai didi

Volatile关键字

转载 作者:撒哈拉 更新时间:2024-08-21 00:58:11 58 4
gpt4 key购买 nike

背景

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()方法返回之后的操作。

最后此篇关于Volatile关键字的文章就讲到这里了,如果你想了解更多关于Volatile关键字的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

58 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com