JUC并发编程-volatile

目录

1. volatile的两大特性

可见性(Visibility)

有序性(Ordering)

2. 四大屏障

3. 读写屏障插入策略

happens-before与volatile变量规则:

注意事项

4. 原子性

5. 禁重排

6.使用场景

传统的单例模式实现如下:(多线程环境下会出问题)

DCL单例模式实现


1. volatile的两大特性

可见性(Visibility)

  • 当一个线程修改了一个volatile变量时,新值会立即被写入主内存,并且其他线程读取该变量时会从主内存中重新读取最新值。这确保了volatile变量的修改对其他线程立即可见。

有序性(Ordering)

  • volatile可以禁止对声明为volatile的变量前后的操作进行指令重排序优化。即编译器和处理器不会对volatile变量前后的操作进行重排序,保证代码的执行顺序与程序代码顺序相同。

2. 四大屏障

  • LoadLoad屏障

    • 作用:在Load1之后和Load2之前插入LoadLoad屏障,确保Load1数据的读取操作在Load2及后续读取操作之前完成。
    • 目的:防止处理器将后面的读操作提前到前面的读操作之前。
  • StoreStore屏障

    • 作用:在Store1之后和Store2之前插入StoreStore屏障,确保Store1的写入操作在Store2及后续写入操作之前完成。
    • 目的:防止处理器将后面的写操作提前到前面的写操作之前。
  • LoadStore屏障

    • 作用:在Load操作之后和Store操作之前插入LoadStore屏障,确保Load操作的数据读取在Store操作的数据写入之前完成。
    • 目的:防止处理器将写操作提前到读操作之前。
  • StoreLoad屏障

    • 作用:在Store操作之后和Load操作之前插入StoreLoad屏障,确保Store操作的数据写入在Load操作的数据读取之前完成。
    • 目的:这是所有屏障中最强大的一个,它不仅保证了屏障前后的读写操作的顺序,还保证了屏障前的写操作对屏障后的读操作可见。

volatile变量的读写场景中,具体会用到以下屏障:

  • 读操作

    • 在读取volatile变量之前,会插入一个LoadLoad屏障和一个LoadStore屏障,用来防止读取操作被重排序。
  • 写操作

    • 在写入volatile变量之后,会插入一个StoreStore屏障和一个StoreLoad屏障,用来确保写入操作对其他线程立即可见。

这些内存屏障保证了volatile变量在多线程环境下的可见性和有序性,是JVM底层对Java内存模型(JMM)的一种实现。需要注意的是,这些屏障的实现细节依赖于具体的CPU架构和JVM的版本。

3. 读写屏障插入策略

happens-before与volatile变量规则:

第一个操作第二个操作:普通读写第二个操作:volatile读第二个操作:volatile写
普通读写可以重排可以重排不可以重排
volatile读不可以重排不可以重排不可以重排
volatile写可以重排不可以重排不可以重排

注意事项

  • 屏障的顺序性:屏障确保了操作的顺序性,防止了重排序的发生,这对于维护多线程之间的内存可见性至关重要。
  • 性能影响:由于屏障会阻止指令的重排序,这可能会对程序的性能产生一定的影响。因此,应该只在确实需要保证可见性和有序性的情况下使用volatile变量。
  • JVM和CPU架构差异:不同的JVM实现和不同的CPU架构可能会对屏障的实现有所不同,但它们都必须遵守Java内存模型(JMM)的规范。

4. 原子性

volatile的变量复合操作不具有原子性

在多线程环境中,如果你需要一个复合操作具有原子性,仅仅使用volatile是不够的。你需要使用锁或其他原子操作机制来确保操作的原子性。

5. 禁重排

为了防止指令重排序,可以使用volatile关键字、锁(如synchronized)这些机制来禁止重排序。

volatile只是确保了可见性,但是无法保证多个线程可能会同时读取同一个volatile变量的值,然后基于这个值进行计算,并写回新值,导致结果不正确。需要通过加锁的方式解决。

6.使用场景

  • 单一赋值例如i=10这种操作可以,但是复合运算例如类似i++这种操作不可以
  • 状态标识,判断业务是否结束
  • 开销较低的读操作,写读策略
  • DCL双端锁的发布

DCL(Double-Checked Locking)是一种优化单例(Singleton)模式的方法,旨在减少创建单例对象时同步代码块的开销。在传统的单例模式实现中,为了保证单例的唯一性,通常会使用一个同步块来确保在多线程环境中只有一个线程能够创建实例。

传统的单例模式实现如下:(多线程环境下会出问题)

public class Singleton {private static Singleton instance;private Singleton() {// 私有构造函数,防止外部创建实例}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

DCL单例模式实现

DCL单例模式试图通过减少同步块的使用来优化性能。它的核心思想是先检查实例是否已经创建,如果没有创建,再使用同步块来创建实例。这样可以避免在实例已经创建的情况下多次执行同步块。

public class Singleton {private static volatile Singleton instance;private Singleton() {// 私有构造函数,防止外部创建实例}public static Singleton getInstance() {if (instance == null) { // 第一次检查synchronized (Singleton.class) { // 加锁if (instance == null) { // 第二次检查instance = new Singleton(); // 创建实例}}}return instance;}
}

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

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

相关文章

Apache Doris 使用 CBO 和 RBO 结合的优化策略

Apache Doris 在查询优化方面通过结合 RBO 和 CBO,实现了对简单和复杂查询的高效优化。RBO 负责处理常量折叠、子查询改写和谓词下推等基础优化操作,而 CBO 则在 Join Reorder 等复杂场景中发挥作用。这种结合策略使得 Apache Doris 能够在面对各种查询场景时,既能保证优化过…

大数据技术之 Flume概述、安装(1)

目录 Flume 概述 Flume 定义 为什么选用 Flume Flume 基础架构 Agent Source Sink Channel Event Flume 安装 Flume 安装部署 安装地址 安装部署 Flume 概述 Flume 定义 Flume 是 Cloudera 提供的一个高可用的、高可靠的、分布式的海量日志采集、聚合和传输的系统。Flume…

Clickhouse集群化(六)clickhosue-operator学习

1. Custom Resource元素 apiVersion: "clickhouse.altinity.com/v1" kind: "ClickHouseInstallation" metadata:name: "clickhouse-installation-test" 这是clickhouse operator自定义的资源ClickHouseInstallation 1.1. .spec.defaults spe…

Webbench1.5安装使用Ubuntu

1、安装依赖包 sudo apt-get update sudo apt-get install libtirpc-dev2、安装Webbench1.5 参考https://github.com/baiguo/webbench-1.5 # 可能需要root权限,我是切换到root用户才安装成功 wget http://home.tiscali.cz/~cz210552/distfiles/webbench-1.5.tar.…

安卓系统 XBL阶段详解

在安卓系统的启动流程中,XBL(eXtensible Boot Loader 或 Secondary Bootloader)是一个关键阶段,特别是在使用QualComm(高通)等SOC(System on Chip)的设备上。以下是对XBL阶段的详细解…

小程序全局本地存储和读取数据

globalData:全局存储信息 定义全局数据(在 app.js 中): 在 app.js 中,你可以通过 globalData 属性定义全局数据 // app.js App({globalData: {userInfo: null,systemInfo: null,theme: light},onLaunch() {console.…

怎么把两个pdf合并成一个pdf?学会这7招,1分钟轻松搞定!

新手小白如何将pdf合并成一个文件?pdf是目前较为主流的一种传输格式,内容包含了丰富的多媒体数据,包括文本、图像、表格等多种元素,很多企业和教育工作者都喜欢使用pdf格式。 pdf文件体积较小,兼容性高,平时…

大数据学习路线基础指南‌

随着信息技术的迅猛发展,‌大数据已成为当今社会的热门话题。‌无论是企业决策、‌市场分析还是科学研究,‌大数据都扮演着举足轻重的角色。‌对于想要投身这一领域的学习者来说,‌制定一份清晰、‌系统的大数据学习路线是至关重要的。‌提供…

Jmeter性能关注指标详解

进行性能测试时,有几个关键的性能指标需要关注,以评估系统的性能和稳定性 一、性能关注指标包含: 响应时间、吞吐量、错误率、资源利用率/使用率(CPU占用率、内存使用率、磁盘I/O等待率、网络I/O) Tips:初步查看数据结果–响应时…

海睿思通过华东江苏大数据交易中心数商认证,提供高质量数据治理服务!

近日,中新赛克海睿思成功通过华东江苏大数据交易中心的数商认证,获得华东江苏大数据交易中心颁发的“数据治理服务商”证书。 华东数交是在实施“国家大数据战略”大背景下,经国家批准的华东地区首个省级特色数据要素交易平台,致力…

学习前端面试知识(14)

2024-8-21 打卡第十四天 js的数据类型 基本类型:String,Number,Object,Null,undefined,Boolean es6之后引入:Symbol,BigInt 判断方式:typeof,instanceof…

鸿蒙HarmonyOS开发:如何使用第三方库,加速应用开发

文章目录 一、如何安装 ohpm-cli二、如何安装三方库1、在 oh-package.json5 文件中声明三方库,以 ohos/crypto-js 为例:2、安装指定名称 pacakge_name 的三方库,执行以下命令,将自动在当前目录下的 oh-package.json5 文件中自动添…

打造敏捷开发环境:JNPF低代码平台的实践与探索

在数字化转型的浪潮中,企业对软件开发的敏捷性和效率提出了更高的要求。传统的软件开发模式通常耗时长、成本高昂,难以迅速适应市场变化。低代码平台的出现,为解决这一问题提供了新的视角。本文将探讨如何运用JNPF低代码平台构建敏捷开发环境…

Tailor:免费开源 AI 视频神器,创作者必备利器

目录 引言一、创新特性,引领视频编辑新潮流1. 智能人脸剪辑2. 精准语音剪辑3. 自动化口播生成4. 多样化字幕生成5. 一键式色彩生成 二、简单易用,新手也能快速上手1. 下载和安装2. 功能选择3. 操作流程 三、广泛应用,满足不同创作需求四、代码…

Python学习-数据库操作

一、安装python库 pip install mysql-connector-python import mysql import re 安装库并导入包 二、定义数据库连接属性: conn mysql.connector.connect(host192.168.1.30, # 替换为你的数据库主机名userkeyijie, # 替换为你的数据库用户名password19kyj20St…

《机器学习》—— AUC评估指标

文章目录 一、什么是AUC?1、什么是ROC曲线?2、ROC曲线的绘制 二、如何计算AUC的值三、代码实现AUC值的计算四、AUC的优缺点 一、什么是AUC? 机器学习中的AUC(Area Under the Curve)是一个重要的评估指标,特…

springboot故障分析FailureAnalyzer

org.springframework.boot.diagnostics.FailureAnalyzer是springboot框架中的一个接口,用于为应用程序启动失败提供详细的诊断报告。当springboot应用程序无法正常启动时,springboot会尝试查找一个或多个实现了FailureAnalyzer接口的类,以提供…

网络游戏运营

游戏运营是将一款游戏平台推入市场,并通过一系列的策略和行动,使玩家从接触、认识到最终成为忠实玩家的过程。这一过程涵盖了多个方面,包括前期准备、上线运营、活动策划、数据分析、渠道合作以及用户维护等。以下是对游戏运营的详细解析&…

HarmonyOS--认证服务-操作步骤

HarmonyOS–认证服务 文章目录 一、注册华为账号开通认证服务二、添加项目:*包名要与项目的包名保持一致三、获取需要的文件四、创建项目:*包名要与项目的包名保持一致五、添加json文件六、加入请求权限七、加入依赖八、修改构建配置文件:bui…

软硬链接

建立软连接 ln -s 指向的文件 软连接文件 建立硬连接 ln 原来文件 硬连接文件 上面我们发现,建立的软链接文件的inode编号和指向文件不同,而建立的硬链接文件inode编号没变,为什么呢? 为什么不能给目录创建硬链接&#xff1f…