volatile 原理

news2024/9/27 5:52:17

volatile 的底层实现原理是内存屏障,Memory Barrier(Memory Fence)

  • 对 volatile 变量的写指令后会加入写屏障
  • 对 volatile 变量的读指令前会加入读屏障

如何保证可见性

写屏障(sfence)保证在该屏障之前的,对共享变量的改动,都同步到主存当中

public void actor2(I_Result r) {
    num = 2;
    ready = true; // ready 是 volatile 赋值带写屏障
    // 写屏障
}

而读屏障(lfence)保证在该屏障之后,对共享变量的读取,加载的是主存中最新数据

public void actor1(I_Result r) {
    // 读屏障
    // ready 是 volatile 读取值带读屏障
    if(ready) {
        r.r1 = num + num;
    } else {
        r.r1 = 1;
    }
}

 如何保证有序性

写屏障会确保指令重排序时,不会将写屏障之前的代码排在写屏障之后

public void actor2(I_Result r) {
    num = 2;
    ready = true; // ready 是 volatile 赋值带写屏障
    // 写屏障
}

 读屏障会确保指令重排序时,不会将读屏障之后的代码排在读屏障之前

public void actor1(I_Result r) {
    // 读屏障
    // ready 是 volatile 读取值带读屏障
    if(ready) {
        r.r1 = num + num;
    } else {
        r.r1 = 1;
    }
}

还是那句话,不能解决指令交错:

  • 写屏障仅仅是保证之后的读能够读到最新的结果,但不能保证读跑到它前面去
  • 而有序性的保证也只是保证了本线程内相关代码不被重排序 

 以上的实现特点是:

  • 懒惰实例化
  • 首次使用 getInstance() 才使用 synchronized 加锁,后续使用时无需加锁
  • 有隐含的,但很关键的一点:第一个 if 使用了 INSTANCE 变量,是在同步块之外

但在多线程环境下,上面的代码是有问题的,getInstance 方法对应的字节码为:

0: getstatic #2 // Field INSTANCE:Lcn/itcast/n5/Singleton;
3: ifnonnull 37
6: ldc #3 // class cn/itcast/n5/Singleton
8: dup
9: astore_0
10: monitorenter
11: getstatic #2 // Field INSTANCE:Lcn/itcast/n5/Singleton;
14: ifnonnull 27
17: new #3 // class cn/itcast/n5/Singleton
20: dup
21: invokespecial #4 // Method "<init>":()V
24: putstatic #2 // Field INSTANCE:Lcn/itcast/n5/Singleton;
27: aload_0
28: monitorexit
29: goto 37
32: astore_1
33: aload_0
34: monitorexit
35: aload_1
36: athrow
37: getstatic #2 // Field INSTANCE:Lcn/itcast/n5/Singleton;
40: areturn

其中

  • 17 表示创建对象,将对象引用入栈 // new Singleton
  • 20 表示复制一份对象引用 // 引用地址
  • 21 表示利用一个对象引用,调用构造方法
  • 24 表示利用一个对象引用,赋值给 static INSTANCE

也许 jvm 会优化为:先执行 24,再执行 21。如果两个线程 t1,t2 按如下时间序列执行: 

        关键在于 0: getstatic 这行代码在 monitor 控制之外,它就像之前举例中不守规则的人,可以越过 monitor 读取
INSTANCE 变量的值
        这时 t1 还未完全将构造方法执行完毕,如果在构造方法中要执行很多初始化操作,那么 t2 拿到的是将是一个未初
始化完毕的单例
        对 INSTANCE 使用 volatile 修饰即可,可以禁用指令重排,但要注意在 JDK 5 以上的版本的 volatile 才会真正有效 

Synchronized关键字可以保证线程的互斥访问和可见性,但它并不能保证有序性。具体而言,即使一个线程已经执行完了synchronized代码块或方法,其内部对共享变量的修改操作也不一定立即对其他线程可见。

这是因为,在多个线程中,线程的调度是由操作系统和JVM共同决定的,并不是由程序控制的。因此,如果两个线程访问同一个资源,可能存在一种情况,即一个线程已经获取到了锁,但由于某种原因(如I/O操作、线程调度等),导致它暂停了一段时间,期间另一个线程也获得了锁并修改了共享变量,这样在第一个线程重新运行时,它的本地缓存并没有及时刷新,就会导致数据的不一致性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/738379.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

液晶仪表业务去年赚了4个亿,又一家汽车电子厂商冲刺IPO

液晶仪表&#xff0c;有多赚钱&#xff1f; 本周&#xff0c;随着天有为电子首次对外发布IPO招股说明书&#xff0c;这家专注于电子式组合仪表、全液晶组合仪表和双联屏仪表等产品的传统汽车仪表企业&#xff0c;揭开了过去几年的财务数据。 作为一家传统汽车仪表转型升级的典…

sqlserver导入外部数据文件

1、外部数据文件存为txt格式&#xff0c;可以带中文标题保存。 2、登录链接数据库服务器&#xff0c;选择任意一个数据库右键-任务-导入数据-数据源&#xff1a;选择Flat File Sourse 平面文件.-文件名&#xff1a;选择文件路径-浏览一下列是否对应上。-下一步-目标&#xff1a…

WebStorm配置代码模板【以vue模板为例,提供vue代码模板】

配置过程 引言 为了便于开发&#xff0c;提高生产效率&#xff0c;我们通常会复制粘贴一些共同代码&#xff0c;在WebStorm中&#xff0c;可以将这些共同代码制作成模板&#xff0c;在使用的时候&#xff0c;只需要输入关键字点击按键即可将模板的代码粘贴到代码文件中&#…

免费申域名

申请地址&#xff1a;https://nic.eu.org/ 英国人地址生成器&#xff1a;https://www.shenfendaquan.com/Index/index/ying_guo_shen_fen_sheng_cheng 1、注册 填写注册信息 进入注册页面&#xff0c;输入注册信息。这里我们打开英国人地址生成器&#xff0c;用英国的信息注…

数据库应用:MySQL数据库使用与管理

目录 一、理论 1.MySQL基本操作 2.数据类型 2.使用MySQL数据库 二、实验 1.查看数据库结构 2.创建及删除库和表 3.管理表中的数据记录 4.修改表名和表结构 5.查看、修改字符集 三、问题 1.表导入新记录报错 四、总结 一、理论 1.MySQL基本操作 &#xff08;1&…

【sql注入-延时注入】sleep()、benchmark()函数 延时注入

目录 sleep()、benchmark()延时注入 一、语法介绍&#xff1a; 二、延时注入 三、不同数据库 网络安全小圈子 sleep()、benchmark()延时注入 一、语法介绍&#xff1a; 版本&#xff1a; sleep() MySQL>5.7.8 benchmark() MySQL>5.7.5 语法&#xff1a; 使用…

孤立随机森林(Isolation Forest)(Python实现)

目录 1 简介 2 孤立随机森林算法 2.1 算法概述 2.2 原理介绍 2.3 算法步骤 3 参数讲解 4 Python代码实现 5 结果 1 简介 孤立森林&#xff08;isolation Forest&#xff09;是一种高效的异常检测算法&#xff0c;它和随机森林类似&#xff0c;但每次选择划分属性和划分点&…

Linux5.95 ELK企业级日志分析系统

文章目录 计算机系统5G云计算第四章 LINUX ELK 企业级日志分析系统一、ELK 概述1.ELK 简介1&#xff09;ElasticSearch2&#xff09;Kiabana3&#xff09;Logstash4&#xff09;可以添加的其它组件&#xff1a;Filebeat5&#xff09;缓存/消息队列&#xff08;redis、kafka、Ra…

Ubuntu 18.04 下 uhd+gnuradio 安装指南,国产B210

安装ubutnu18.04&#xff0c;换源&#xff0c;apt-get update 一、虚拟机设置以及安装low-latency内核 给虚拟机分配尽可能多的cpu及内存。在USB控制器选项中&#xff0c;将USB兼容性设置为USB 3.1。 USRP B210需要用USB线连接到电脑的USB 3.0/3.1接口上&#xff0c;实现供电…

Melon库运用——栈篇

头文件片段 // mln_stack.htypedef struct mln_stack_node_s {void *data;struct mln_stack_node_s *prev;struct mln_stack_node_s *next; } mln_stack_node_t;typedef struct {mln_stack_node_t *bottom;mln_stack_node_t *top;mln_stac…

喜讯|电巢科技与陕西理工大学“新工科人才联合培养基地”签约暨揭牌仪式成功举行

7月6日上午&#xff0c;深圳市电巢科技有限公司联合陕西理工大学物理与电信工程学院在校内举行产学研座谈会&#xff0c;并完成了“新工科人才联合培养基地”的签约暨揭牌仪式。陕西理工大学物电学院党委书记韩强&#xff0c;院长卢超&#xff0c;副书记潘峰&#xff0c;副院长…

吸烟(抽烟)检测和识别2:Pytorch实现吸烟(抽烟)检测和识别(含吸烟(抽烟)数据集和训练代码)

吸烟(抽烟)检测和识别2&#xff1a;Pytorch实现吸烟(抽烟)检测和识别(含吸烟(抽烟)数据集和训练代码) 目录 吸烟(抽烟)检测和识别2&#xff1a;Pytorch实现吸烟(抽烟)检测和识别(含吸烟(抽烟)数据集和训练代码) 1.吸烟(抽烟)检测和识别 2.吸烟(抽烟)数据集 &#xff08;1&am…

msvcp120.dll丢失的解决方法?哪种方法更推荐

msvcp120.dll是一个Windows操作系统的动态链接库文件。它属于Microsoft Visual C Redistributable软件包的一部分。这个文件包含了一些用于C程序编译和运行的函数和类。当某个程序需要使用这些函数和类时&#xff0c;它会在系统中寻找msvcp120.dll文件。如果系统中缺少这个文件…

运行别人gitub上的vue代码

1.删除package-lock.json和node_modules文件 package-lock.json记录了整个node_moudles文件夹的树状结构&#xff0c;还记录了模块的下载地址&#xff0c;但是它是基于项目作者的npm版本库生成的&#xff0c;若不删掉这个依赖文件&#xff0c;容易出现npm版本差异导致的报错。…

性能测试测什么?如何做性能测试?超级详细总结

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 性能测试 负载&a…

深入理解Dockerfile:构建镜像的详细解释与常用命令

目录 1.Dockerfile 简介 2.Dockerfile 指令解析 2.1 FROM 2.2 RUN 2.3 COPY 2.4 ADD 2.5 CMD 2.6 ENTRYPOINT 2.7 ENV 2.8 ARG 2.9 EXPOSE 2.10 WORKDIR 2.11 VOLUME 2.12 USER 3.构建 Docker 镜像的常用命令 3.1 docker build 3.2 docker tag 3.3 docker pu…

银河麒麟V10使用编译安装PostSQL+PostGIS

一、安装环境 银河麒麟V10 1、PostGIS简介 PostGIS是对象关系型数据库系统PostgreSQL的一个扩展&#xff0c;PostGIS提供如下空间信息服务功能&#xff1a; 空间对象、空间索引、空间操作函数和空间操作符。同时&#xff0c;PostGIS遵循OpenGIS的规范。 二、使用make安装Post…

Day49

思维导图 练习 闹钟设计 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> #include <QPushButton> #include <QLabel> #include <QLineEdit> #include <QTextEdit> #include <QTimer> …

【C++】STL——stack和queue使用及模拟实现

&#x1f680; 作者简介&#xff1a;一名在后端领域学习&#xff0c;并渴望能够学有所成的追梦人。 &#x1f681; 个人主页&#xff1a;不 良 &#x1f525; 系列专栏&#xff1a;&#x1f6f8;C &#x1f6f9;Linux &#x1f4d5; 学习格言&#xff1a;博观而约取&#xff0…

ICG试剂大合集:ICG-COOH/NHS/NH2/Maleimide/alkyne/N3

荧光染料及其荧光标记技术一直是生物领域常用的产品和技术&#xff0c;标记荧光的波长从300nm到1000nm&#xff0c;除了常见的FITC、FAM等荧光标记染料外&#xff0c;还包括Cy3&#xff0c;Cy3.5&#xff0c;Cy5, Cy5.5&#xff0c;Cy7&#xff0c;Cy7.5&#xff0c;ICG各种衍生…