synchronized, volatile 在 DCL 的作用
背景
最近在看设计模式,在单例模式的 Double Check Lock(DCL)中,存在两个关键字:volatile & synchronized。
之前都知道 DCL 怎么写,直接套娃。但是这两关键字在单例里面的作用还没深究过,于是就自言自语一篇文章。
单例模式代码
public class Single {private static volatile Single INSTANCE;private Single(){}public static Single getInstance(){//first check objectif(INSTANCE == null){//locks in the class dimensionsynchronized (Single.class){//second check objectif(INSTANCE == null){INSTANCE = new Single();}}}return INSTANCE;}
}
synchronized & volatile 作用
synchronized 作用
synchronized 是 java 的重量级锁,可作用于方法维度、代码块维度。具体到底层字节码就是 monitor enter & monitor exit。
volatile 作用
volatile 有两个作用
- 保证可见性。
修饰的变量从主内存 copy 到工作内存,修改后写回到主内存。
作用原理就是读写前 JVM 加一个内存屏障,通过 happen before 原则确保修改可见于读取。
主内存:类比成 JVM 堆
工作内存:类比成 JVM 虚拟机栈
- 禁止指令重排序。
对象初始化步骤
- 分配内存空间
- 实例变量初始化
- 执行初始化代码块
- 调用构造函数
- 静态变量初始化
- 返回对象引用
刨除非必要步骤,上述 6 步剩下 3 步
- 分配内存空间
- 调用构造函数
- 返回对象引用
synchronized & volatile 在 DCL 缺失的问题
有 synchronized 没有 volatile
由于指令重排序的优化手段,上述创建对象的 1 -> 2 -> 3, 可能顺序变成了 1 -> 3 -> 2。
没有禁止重排序,顺序变了,中间的第三步返回是个空对象,并发情况下就 G 了,另一线程拿的是空对象。
有 volatile 没有 synchronized
并发情况下, A B 两个线程都通过了等于 null 的校验,开始执行创建对象的操作。
上述创建对象说的 1 -> 2 -> 3, A B 两个线程都有可能走完 1 & 2,最后单例对象会是执行慢的线程返回引用的那个。构造函数会执行两遍,违反了单例模式的初衷。
总结
synchronized & volatile 的作用就很明显。
synchronized 保障构造函数只执行一遍,对象也只有一个。
volatile 保障极端情况下不会返回空对象。
题外话
- 为什么 synchronized 修饰的是代码块,不是静态方法 getInstance ?
为了提升获取单例对象的运行效率。
synchronized 修饰代码块,只会影响进入代码块瞬间的其他线程。
synchronized 修饰方法,会影响调用方法的所有线程。
- 为什么进入 synchronized 修饰代码块后,还要判断一下单例对象是否等于 null ?
防止重复创建对象。
假设 A B 两个线程
- A 线程进入同步块,还在上述说的对象初始化三步里面,B 线程进来了,在 synchronized 代码块外自旋。
- A 线程执行完了,B 线程进代码块了,这时若不判断是否为 null,就会重复创建对象。
本文首发于cartoon的博客
转载请注明出处:https://cartoonyu.github.io
相关文章:
synchronized, volatile 在 DCL 的作用
背景 最近在看设计模式,在单例模式的 Double Check Lock(DCL)中,存在两个关键字:volatile & synchronized。 之前都知道 DCL 怎么写,直接套娃。但是这两关键字在单例里面的作用还没深究过,…...
Java进阶笔记(中级)
-----接Java进阶笔记(初级)----- 目录 集合多线程 集合 ArrayList 可以通过List来接收ArrayList对象(因为ArrayList实现了List接口) 方法:接口名 柄名 new 实现了接口的类(); PS: List list new ArrayList();遍历…...
人生总有终点,不必好高骛远
夕阳西下,我漫步在河堤上。河水缓缓流淌,倒映着天边最后一抹晚霞。岸边垂柳依依,枝条轻拂水面,荡起一圈圈涟漪。这涟漪由近及远,渐渐消散在暮色中,如同我们每个人在时间长河中泛起的微澜。 记得年少时&…...
C#中堆和栈的区别
C#中的堆(Heap)和栈(Stack)详解 基本概念 栈(Stack) 栈是一个后进先出(LIFO)的内存结构由系统自动分配和释放存储空间连续,大小固定主要用于存储值类型和对象引用 堆…...
如何利用i18n实现国际化
1.首先新建i18.js文件 // i18n配置 import { createI18n } from vue-i18n // import ElementPlus from element-plus import zhCn from element-plus/es/locale/lang/zh-cn import zh from ./zh-cn import en from ./en import ru from ./ru const messages {en_US: {...en,//…...
SpringMVC响应
第一章:数据处理及跳转 1. 结果跳转方式 ①.ModelAndView 设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 . <bean id"templateResolver" class"org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolv…...
深入理解特征值与稳定性密码:以弹簧 - 质量 - 阻尼典型二阶系统为例
从看特征值决定稳定性的原因 摘要 本文以弹簧 - 质量 - 阻尼系统这一典型二阶系统为研究对象,深入剖析特征值决定系统稳定性的内在原因。通过详细的数学推导和直观的物理意义阐释,全面揭示了特征值与系统稳定性之间的紧密关联,为理解和分析…...
python pandas 读取合并单元格并保留合并信息
读取合并单元格并保留合并信息 当我们只是使用 pandas 的 read_excel 方法读取 Excel 文件时,我们可能会遇到一个很棘手的问题:合并单元格的信息将会丢失,从而导致我们的数据出现重复或缺失的情况。 在本篇文章中将介绍使用 pandas 正确地读…...
Go-Gin Web 框架完整教程
1. 环境准备 1.1 Go 环境安装 Go 语言(或称 Golang)是一个开源的编程语言,由 Google 开发。在开始使用 Gin 框架之前,我们需要先安装 Go 环境。 安装步骤: 访问 Go 官网下载页面:https://golang.org/dl…...
机器学习专业毕设选题推荐合集 人工智能
目录 前言 毕设选题 开题指导建议 更多精选选题 选题帮助 最后 前言 大家好,这里是海浪学长毕设专题! 大四是整个大学期间最忙碌的时光,一边要忙着准备考研、考公、考教资或者实习为毕业后面临的升学就业做准备,一边要为毕业设计耗费大量精力。学长给大家整理…...
Java程序员 面试如何介绍项目经验?
项目经历是面试过程中重点问的,但是很多人在回答的时候往往会有问题: 重点是介绍项目,而忽略了个人的经历。 经历是你做了什么、你怎么做的、做完后的结果。例如:项目中的哪些部分是你做的?你是不是核心人员…...
YONBIP后端环境搭建-IDEA
1、IDEA环境搭建 1.1、插件安装 打开设置窗口,添加自定义插件存储库路径。 https://nccdev.yonyou.com/ide/idea/latest/updatePlugin.xml 在 Marketplace 中搜索 YonBuilder Premium开发者工具 ,点击安装。 1.2、Home配置 点击Home配置按钮…...
Java 微服务实用指南(一)
Java 微服务:基础 要真正理解 Java 微服务,就必须从最基本的东西开始:为人诟病的 Java 大型单体应用是什么,它的优点和缺点是什么。 什么是 Java 大型单体应用? 假设你正在为一家银行或一家金融科技初创公司工作。你为…...
Windows图形界面(GUI)-QT-C/C++ - QT Frame
公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 一、概述 二、使用场景 1. 分隔内容区域 2. 装饰性边框 3. 自定义控件容器 三、常见样式 1. 框架形状(Shape) 2. 框架阴影(Shadow)…...
优选算法合集————双指针(专题二)
好久都没给大家带来算法专题啦,今天给大家带来滑动窗口专题的训练 题目一:长度最小的子数组 题目描述: 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl1, …...
WebSocket协议里客户端发送给服务器的数据会用4字节的掩码循环异或的分析
首先,我需要回顾WebSocket协议中对掩码处理的具体要求。根据RFC 6455,客户端发送到服务器的帧必须使用掩码,而服务器发送的帧不需要掩码。掩码是4字节的,应用于有效载荷数据,每个字节依次与掩码的对应字节异或…...
【字节青训营-9】:初探字节微服务框架 Hertz 基础使用及进阶(下)
本文目录 一、Hertz中间件Recovery二、Hertz中间件跨资源共享三、Hertz 响应四、Hertz请求五、Hertz中间件Session 一、Hertz中间件Recovery Recovery中间件是Hertz框架预置的中间件,使用server.Default()可以默认注册该中间件,为Hertz框架提供panic回复…...
新版AndroidStudio 修改 jdk版本
一、问题 之前,在安卓项目中配置JDK和Gradle的过程非常直观,只需要进入Android Studio的File菜单中的Project Structure即可进行设置,十分方便。 如下图可以在这修改JDK: 但是升级AndroidStudio之后,比如我升级到了Android Stu…...
cocos spine执行动画报错Cannot read properties of null (reading ‘data‘)
cocos v3.8.3 当想this.spine.setAnimation(0, "action1", false);播放spine动画时报错↓ 解决方法一: 在setAnimation之前调用this.spine.__preload() 解决方法二: 不要让spine或其父节点通过active显隐...
笔记:新能源汽车零部件功率级测试怎么进行?
摘要:本文旨在梳理主机厂对新能源汽车核心零部件功率级测试需求,通过试验室的主流设备仪器集成,快速实现试验方案搭建,并体现测试测量方案的时效性、便捷性优势。目标是通过提升实现设备的有效集成能力、实现多设备测试过程的有效协同、流程化测试,可快速采集、分析当前数…...
【starrocks学习】之将starrocks表同步到hive
目录 方法 1:通过HDFS导出数据 1. 将StarRocks表数据导出到HDFS 2. 在Hive中创建外部表 3. 验证数据 方法 2:使用Apache Spark同步 1. 添加StarRocks和Hive的依赖 2. 使用Spark读取StarRocks数据并写入Hive 3. 验证数据 方法 3:通过…...
Linux提权--SUDO提权
sudo 是 Linux 中常用的特权管理工具,允许普通用户以其他用户(通常是 root 用户)的身份运行命令。如果配置不当,攻击者可能通过滥用 sudo 权限来提升自己的权限。 一.常见的 sudo 提权方法: 误配置的 sudo 权限&…...
【AIGC提示词系统】基于 DeepSeek R1 + Claude 的新年运势占卜系统设计与实现
提示词在最下方 DeepSeek R1调试了整体的提示词,使用Claude进行渲染 引言 在人工智能与传统文化交融的今天,如何让 AI 充分理解并传递东方玄学文化的精髓,成为一个极具挑战性的课题。本文将详细介绍一个基于 Claude 的新年运势占卜系统的设计…...
11. Global Object 全局对象的使用
Global Object 全局对象 1 引言2 制作全局对象3 调用全局对象4 扩展使用1 引言 全局对象适用于大量重复的对象,比如阀门,电机等,如果这些设备的基本逻辑与状态都是一样的,那么就可以使用全局对象的方法来做HMI,省时省力。并且在后期修改的时候只需要修改全局对象即可。 …...
Java synchronized锁升级
偏向锁、轻量级锁和重量级锁是Java中synchronized关键字的三种锁状态,用于优化多线程环境下的性能。以下是它们的简要说明: 1. 偏向锁(Biased Locking) 目的:减少无竞争时的锁开销。适用场景:只有一个线程…...
【Hadoop】Hadoop的HDFS
这里写目录标题 HDFS概述HDFS产出背景及定义HDFS产生背景HDFS定义 HDFS优缺点HDFS优点HDFS缺点 HDFS组成架构HDFS文件块大小 HDFS的Shell操作常用命令实操准备工作上传下载HDFS直接操作 HDFS的API操作客户端环境准备HDFS的API案例实操HDFS文件上传HDFS文件下载HDFS文件更名和移…...
JAVA异步的TCP 通讯-客户端
一、客户端代码示例 import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; import java.util.concurrent.ExecutorService; impo…...
4.回归与聚类算法 4.1线性回归
4.1.1 线性回归的原理 1 线性回归应用场景: 房价预测 销售额度预测 金融:贷款额度预测,利用线性回归以及系数分析因子 2 什么是线性回归 1) 定义:利用回归方程(函数)对一个或者多个自变量…...
联想拯救者开机进入bios
如果你的联想拯救者(Lenovo Legion)笔记本电脑开机后直接进入 BIOS 设置界面,可能是以下原因之一导致的。以下是解决方法: 1. 检查启动顺序 进入 BIOS 后,找到 Boot(启动)选项卡。检查启动顺序…...
【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(四)
✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨ 文章所属专栏:贪心算法篇–CSDN博客 文章目录 前言例题1.合并区间2.无重叠的区间3.用最少数量的箭引爆气球…...
Junit5使用教程(3)
第三部分:JUnit 5 进阶 3. 动态测试 一、动态测试是什么? 动态测试(Dynamic Test)允许在运行时生成测试用例,而不是在编译时通过 Test 静态定义。它通过 TestFactory 注解标记的方法动态生成一组测试用例࿰…...
WPS中解除工作表密码保护(忘记密码)
1.下载vba插件 项目首页 - WPS中如何启用宏附wps.vba.exe下载说明分享:WPS中如何启用宏:附wps.vba.exe下载说明本文将详细介绍如何在WPS中启用宏功能,并提供wps.vba.exe文件的下载说明 - GitCode 并按照步骤安装 2.wps中点击搜索,输入开发…...
通向AGI之路:人工通用智能的技术演进与人类未来
文章目录 引言:当机器开始思考一、AGI的本质定义与技术演进1.1 从专用到通用:智能形态的范式转移1.2 AGI发展路线图二、突破AGI的五大技术路径2.1 神经符号整合(Neuro-Symbolic AI)2.2 世界模型架构(World Models)2.3 具身认知理论(Embodied Cognition)三、AGI安全:价…...
kamailio-osp模块
该文档详细讲解了如何在Kamailio中配置和使用OSP模块(Open Settlement Protocol Module),以实现基于ETSI标准的安全多边对等互联(Secure Multi-Lateral Peering)。以下是核心内容的总结: 1. 模块功能 OSP模…...
【Linux网络编程】:URL(encode),HTTP协议,telnet工具
🎁个人主页:我们的五年 🔍系列专栏:Linux网络编程 🌷追光的人,终会万丈光芒 🎉欢迎大家点赞👍评论📝收藏⭐文章 Linux网络编程笔记: https://mp.csdn…...
SpringMVC SpringMVC响应 一、数据处理及跳转
1. 结果跳转方式 ①.ModelAndView 设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 <bean id"templateResolver" class"org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver"><property name"p…...
C++SLT(三)——list
目录 一、list的介绍二、list的使用list的定义方式 三、list的插入和删除push_back和pop_backpush_front和pop_frontinserterase 四、list的迭代器使用五、list的元素获取六、list的大小控制七、list的操作函数sort和reversemergeremoveremove_ifuniqueassignswap 一、list的介…...
基于Coze平台实现抖音链接提取文案转小红书文案的智能体开发全流程解析
文章目录 引言:跨平台内容运营的AI解法实例最终效果1. 平台特性对比与转化需求分析1.1 用户画像与内容风格对比1.2 文案转化核心需求2. Coze平台技术架构解析2.1 Coze核心能力矩阵2.2 关键技术组件选型3. 智能体工作流设计3.1 完整处理流程3.2 关键节点说明4. 核心模块实现详解…...
32. 最长有效括号
动态规划 dp[i]表示以i下标为结尾的最长有效括号的长度,取dp[i]中的最大值即可。 i从1开始判断,只有s[i])才需要判断: 如果s[i-1](,那么dp[i]dp[i-2]2,注意判断i-2的范围否则,如果dp[i-1]>0࿰…...
Linux常见问题解决方法--2
如何反爬 后台对访问进行统计,如果单个 IP 访问超过阈值,予以封锁 后台对访问进行统计,如果单个 session 访问超过阈值,予以封锁 后台对访问进行统计,如果单个 userAgent 访问超过阈值,予以封锁 以上的组…...
STM32H7和F7 主要区别
STM32H7和F7系列是STMicroelectronics推出的高性能ARM Cortex-M微控制器系列,二者在性能、外设和用途上有显著区别。以下是它们的主要区别: 1. 内核与性能 STM32H7: 内核:Cortex-M7(单核或双核,部分型号带…...
软件测试丨PyTorch 图像目标检测
随着人工智能和机器学习的飞速发展,图像目标检测技术在各个领域扮演着越来越重要的角色。无论是在安防监控、自动驾驶车辆,还是在医疗影像分析和智能家居中,图像目标检测都发挥着不可或缺的作用。今天,我们将深入探讨其中一种热门…...
利用TensorFlow.js实现浏览器端机器学习:一个全面指南
引言 随着深度学习技术的不断发展,机器学习已从传统的服务器端运算逐渐转向了前端技术。TensorFlow.js 是 Google 推出的一个用于在浏览器中进行机器学习的开源库,它允许开发者在浏览器中直接运行机器学习模型,而无需依赖后端服务器。Tensor…...
全流程安装DeepSeek开源模型
目录 安装Ollama选择大模型安装大模型对话备注 安装Ollama 安装DeepSeek首先需要安装一个Ollama,这个软件相当于运行DeepSeek模型的底层,没有这个底层就没办法跑DeepSeek AI模型。 下载地址: https://ollama.com/点击下载windows版本&…...
VulnHub | Prime - 1
https://vulnhub.com/entry/prime-1,358/https://vulnhub.com/entry/prime-1,358/ 0x01:靶场简介 Prime 1 是 VulHub 中的一台用于 OSCP 考试练习的靶机。通过本靶机,我们可以系统的了解的渗透测试的全流程。本靶机的通关目标如下: Get The…...
实验十 Servlet(一)
实验十 Servlet(一) 【实验目的】 1.了解Servlet运行原理 2.掌握Servlet实现方式 【实验内容】 1、参考课堂例子,客户端通过login.jsp发出登录请求,请求提交到loginServlet处理。如果用户名和密码相同则视为登录成功,…...
寒假刷题Day22
一、2570. 合并两个二维数组 - 求和法 class Solution { public:vector<vector<int>> mergeArrays(vector<vector<int>>& nums1, vector<vector<int>>& nums2) {int i 0, j 0, n1 nums1.size(), n2 nums2.size();int tmp 0;…...
KES数据库实践指南:探索KES数据库的事务隔离级别
引言 前两篇文章我们详细讲解了如何安装KES金仓数据库,并提供了快速查询和搭建基于coze平台的智能体的解决方案。今天,我们的焦点将放在并发控制机制和事务隔离级别上。 本文将通过一系列实验操作,深入探讨KES数据库中的并发控制机制和事务…...
基于STM32的智能加湿器设计(新版本)
目录 1、设计要求 2、系统功能 3、演示视频和实物 4、系统设计框图 5、软件设计流程图 6、原理图 7、主程序 8、总结 🤞大家好,这里是5132单片机毕设设计项目分享,今天给大家分享的是加湿器。设备的详细功能见网盘中的文章《12、基于…...
Electricity Market Optimization 探索系列(三)
本文参考链接link 电网容量规划是一个寻求最优发电容量的过程,找到的最优发电容量能够可靠地满足未来电网的需求 发电机的容量和发电成本呈正相关关系,一台发电机的发电量不能超过其额定发电容量,结合我之前的博客所说的内容,可…...