volatile关键字解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: volatile关键字解析

并发编程中的三个概念


原子性


原子性其实在数据库中也有体现,拿转账为例,张三给李四转1块钱,业务逻辑为张三减1块钱,李四加一块钱,这些必须同时成功。此处略去一万字。


可见性


操作系统


当CPU访问数据的时候,其实是有多级缓存的,如下图所示(深入理解计算机系统 原书第三版 ),当多个CPU去访问一个数据的时候,他会把主存中的数据先缓存到高速缓存里,然后在执行操作,那么此时如果两个CPU同时执行a=a+1操作,如果没有一定的同步方法,那么就会出现修改丢失的问题,因此可见性就是保证当一个CPU或者线程对某一个共享变量修改后,对其他CPU或者线程可见。


11.png


从JMM看


Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程中是用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行。

其实还是和操作系统中一样的问题。需要实现当一个线程对某个变量修改后对其他线程可见。


12.png


有序性


除了引入了时间片以外,由于处理器优化和指令重排等,CPU还可能对输入代码进行乱序执行,比如load->add->save 有可能被优化成load->save->add 。这就是有序性问题。


如下面代码所示,逻辑为先初始化context,然后在做一些事情


  //线程1
    boolean init = false;(1)
    String context = initialContext();(2)
    init = true;(3)
    //线程2
    while (!init){ (4)
      sleep(1L);
    }
    context.doSomeThing();(5)


但是如果出现了重排序的情况,线程1先执行(1)(3),那么此时线程2执行(4),在context还没有初始化的情况下,就进行了操作,这是有问题的。


volatile底层实现


微信截图_20230225145430.png


java源码


其实在java源码中看,volatile其实就是一个关键字


public class Start {
  private static volatile Start ins = null;
  public static Start getInstance(){
    if (ins == null){
      synchronized (Start.class){
        if (ins == null){
          ins = new Start();
        }
      }
    }
    return ins;
  }
  public static void main(String[] args) {
    System.out.println(1);
  }
}


字节码


从字节码角度看,其实就是在一个变量上打一个标记。


13.png


JVM虚拟机规范


14.png


StoreStoreBarier
volatile 写操作
StoreLoadBarier
LoadLoadBarier
volatile 读操作
LoadStoreBarier


操作系统


缓存一致性协议MESI。


lfence,是一种Load Barrier 读屏障。在读指令前插入读屏障,可以让高速缓存中的数据失效,重新从主内存加载数据

sfence, 是一种Store Barrier 写屏障。在写指令之后插入写屏障,能让写入缓存的最新数据写回到主内存

mfence, 是一种全能型的屏障,具备ifence和sfence的能力


目录
相关文章
|
19天前
|
Java 程序员
面试官的加分题:super关键字全解析,轻松应对!
小米,29岁程序员,通过一个关于Animal和Dog类的故事,详细解析了Java中super关键字的多种用法,包括调用父类构造方法、访问父类成员变量及调用父类方法,帮助读者更好地理解和应用super,应对面试挑战。
35 3
|
6天前
|
安全 编译器 C++
C++ `noexcept` 关键字的深入解析
`noexcept` 关键字在 C++ 中用于指示函数不会抛出异常,有助于编译器优化和提高程序的可靠性。它可以减少代码大小、提高执行效率,并增强程序的稳定性和可预测性。`noexcept` 还可以影响函数重载和模板特化的决策。使用时需谨慎,确保函数确实不会抛出异常,否则可能导致程序崩溃。通过合理使用 `noexcept`,开发者可以编写出更高效、更可靠的 C++ 代码。
12 0
|
4月前
|
网络协议 Java 数据库连接
13 Java异常(异常过程解析、throw、throws、try-catch关键字)
13 Java异常(异常过程解析、throw、throws、try-catch关键字)
109 2
|
6月前
|
存储 Java 数据库
Static关键字在Java中的多种用途解析
Static关键字在Java中的多种用途解析
|
6月前
|
JavaScript 前端开发 开发者
JavaScript中的const关键字解析
JavaScript中的const关键字解析
|
5月前
|
存储 C语言
C语言中static关键字的作用与用法解析
C语言中static关键字的作用与用法解析
|
5月前
|
存储 Java 数据库
Static关键字在Java中的多种用途解析
Static关键字在Java中的多种用途解析
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
71 2
|
2月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
76 0
|
2月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
62 0

推荐镜像

更多