单例模式、指令重排序、锁、有序性

今天在回顾单例模式时,我们都知道懒汉式单例中有一种叫做双重检查锁的单例模式。

我们来看下下面的代码有没有问题:
在这里插入图片描述
这段代码我们可以看到,即优化了性能,在多线程情况下,如果实例不为空了,则直接返回了。这样就不用等待排队获取锁了。
同时也保证了线程的安全性,即全程只会出现一个实例。

但是真的没有问题了吗?我们来分析一下:
在执行到 lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();这条语句时,这里是会发生一个指令重排序的问题的。什么是指令重排序呢?
正常的我们创建一个对象,对于底层来说是: a. 内存分配 b. 初始化 c. 返回对象引用

但是由于指令重排序:我们的指令执行过程可能会成为 a. 内存分配 b. 返回对象引用 c. 初始化

如果是我们指令重排序的这种结果。那我们上面的代码就会产生问题了。
即:假设第一个线程执行到了 lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton(); 这条语句,但是只是执行了指令中的 a 、 b 即初始化还没有完成,但此时 lazyDoubleCheckSingleton这个引用已经不为空了,此时第二个线程过来,在外层判断发现lazyDoubleCheckSingleton不等于空,就直接返回了,但此时返回的对象很明显是个半成品,还没有初始化。因此就会导致产生不可预估的错误。

具体为什么会产生指令重排序,或者指令重排序的详细概念请看https://blog.csdn.net/weixin_37841366/article/details/113086438

以上是问题的背景。

但是我的疑问是为什么会产生指令重排序呢?我印象中学习过的JUC不是说加锁:即Synchronized是可以保证 有序性、可见性、原子性的吗?这个赋值创建的语句这不是在Synchronized代码块里面呢吗?怎么会有指令重排序的问题呢?

下面我们就来分析一下为什么会产生这样的问题吧~

首先我们需要先好好理解一下加锁保证的有序性和volatile关键字防止指令重排序保证的有序性的区别。

首先我们需要明确一点:那就是加锁是无法防止指令重排序的。那为什么说他能够保证有序性呢?

我们需要了解一个语义:

编译器和处理器必须遵守as-if-serial语义,即不管怎么重排序(编译器和处理器为了提高并行度),单线程程序的执行结果不能被改变。

因为Synchronized块中的代码相当于是单线程执行的,而因为这个语义的存在,单线程执行的执行结果是保证不能被改变的,因此Synchronized代码块包裹的代码是有序的代码。这里的有序指的是宏观的有序。

但我们的双检查单例为什么靠Synchronized锁做不到保证有序呢?
因为我们在代码块外面的那个if判断是不受Synchronized控制的。Synchronized的内部是有序了。但是外部依旧无序。

因此上面的代码我们需要添加volatile关键字防止指令重排序。让其保证微观上的强有序性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue成绩案例实现添加、删除、显示无数据、添加日期、总分均分以及数据本地化等功能

一、成绩案例 ✅✅✅通过本次案例实现添加、删除、显示无数据、添加日期、总分均分以及数据本地化等功能。 准备成绩案例模板&#xff0c;我们需要在这些模板上面进行功能操作。 <template><div class"score-case"><div class"table">…

Rsync(二十七)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、概述 二、特性 三、应用场景 四、数据的同步方式 五、rsync传输模式 六、rsync应用 七、rsync 命令 1. 格式 1.1 作为远程命令 1. 2 作为rsync服务 2. 选项 3.…

解密:GPT-4框架与训练过程,数据集组成,并行性的策略,专家权衡,推理权衡等细节内容

大家好&#xff0c;我是微学AI&#xff0c;今天给大家解密一下GPT-4框架与训练过程&#xff0c;数据集组成&#xff0c;并行性的策略&#xff0c;专家权衡&#xff0c;推理权衡等细节内容。2023年3月14日&#xff0c;OpenAI发布GPT-4&#xff0c;然而GPT-4的框架没有公开&#…

【ArcGIS Pro二次开发】(46):要素类从上到下、从左到右排序

要素类经过编辑之后&#xff0c;【OBJECTID】字段会变得不规律。应部分网友要求&#xff0c;做了这个从上到下、从左到右排序的工具。 不过后来在ArcGIS Pro中发现了一个【排序】工具&#xff0c;已经可以完美实现这个功能需求&#xff0c;发现自己做了个白工。 不过做了不能白…

【最新教程】树莓派安装系统及VNC远程桌面连接

大家好&#xff0c;今天就不给大家介绍PYTHONL ,今天我作为一个刚入坑树莓派的小白&#xff0c;整理了一下自己安装树莓派的整个过程&#xff0c;分享给大家。 目录 树莓派 准备工作&#xff1a; 树莓派远程ssh失败access denied 原因&#xff1a; 树莓派系统安装 1、下载…

hive常用方法

日期类 Date_sub 日期进行加减 &#xff0c;正的减&#xff0c;负的加 select current_date -- 当前日期,date_sub(current_date,1) -- 前一日,date_sub(current_date,-1) -- 后一日 from edw.test;字符类 split 该函数是分割字符串 &#xff0c;按照…

ChatGPT火热之下的冷思考

作为一款基于人工智能的自然语言处理(NLP)​​聊天机器人​​程序&#xff0c;ChatGPT通过大量来自互联网的文本进行训练&#xff0c;并使用深度学习和机器学习算法来理解用户的问题并提供准确的回答。并且&#xff0c;ChatGPT还内置了情感分析、关键字提取和实体识别等功能&am…

【QT】——QListWidget的使用

目录 1.QListWidget和QListWidgetItem 2.外观 2.1列表模式 2.2图标模式 3.常用接口 4.示例 删除列表项 添加列表项 1.QListWidget和QListWidgetItem QListWidget 是qt中的列表框控件&#xff0c;它用于显示多个列表项&#xff0c;列表项对应的类是QListWidgetItem. Q…

qt和vue交互

1、首先在vue项目中引入qwebchannel /******************************************************************************** Copyright (C) 2016 The Qt Company Ltd.** Copyright (C) 2016 Klarlvdalens Datakonsult AB, a KDAB Group company, infokdab.com, author Milian …

MobPush Android For Unity

本文档以unity2020.3.41演示 集成准备 注册账号 使用MobSDK之前&#xff0c;需要先在MobTech官网注册开发者账号&#xff0c;并获取MobTech提供的AppKey和AppSecret&#xff0c;详情可以点击查看注册流程 下载.unitypackage包 打开 Github 下载 MobPush-For-Unity 项目&am…

java项目之贝儿米幼儿教育管理系统(ssm+mysql+jsp)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的贝儿米幼儿教育管理系统。技术交流和部署相关看文章末尾&#xff01; 开发环境&#xff1a; 后端&#xff1a; 开发语言&#xff1a;Java…

队列的表示和操作

队列&#xff1a;队列是仅在表尾进行插入操作&#xff0c;在表头进行删除操作的线性表。 表尾即an端&#xff0c;称为队尾&#xff0c;表头即a1端&#xff0c;称为队头。 队列的存储方式&#xff1a;顺序队列和链式队列 队列顺序表示 #define MAXQSIZE 100 //最大队列长度 …

使用php数组实现双色球的随机选号

一、双色球彩票介绍 双色球是中国福利彩票的一种常见玩法&#xff0c;也是全国彩民最爱的彩种之一。玩法规则是在33个红色球中选择6个数字&#xff0c;在16个蓝色球中选择1个数字&#xff0c;红色球号码区间为1-33&#xff0c;蓝色球号码区间为1-16。可以单式投注或者复式投注…

Python对Excel不同的行分别复制不同的次数

本文介绍基于Python语言&#xff0c;读取Excel表格文件数据&#xff0c;并将其中符合我们特定要求的那一行加以复制指定的次数&#xff0c;而不符合要求的那一行则不复制&#xff1b;并将所得结果保存为新的Excel表格文件的方法。 这里需要说明&#xff0c;在我们之前的文章Pyt…

Python爬虫——urllib_post请求百度翻译

post请求&#xff1a; post的请求参数&#xff0c;是不会拼接在url后面的&#xff0c;而是需要放在请求对象定制的参数中 post请求的参数需要进行两次编码&#xff0c;第一次urlencode&#xff1a;对字典参数进行Unicode编码转成字符串&#xff0c;第二次encode&#xff1a;将字…

【ArcGIS微课1000例】0070:制作宾馆酒店分布热度热力图

本文讲解在ArcGIS中,基于长沙市酒店宾馆分布矢量点数据(POI数据)绘制酒店分布热力图。 相关阅读: 【GeoDa实用技巧100例】004:绘制长沙市宾馆热度图 【ArcGIS Pro微课1000例】0028:绘制酒店分布热力图(POI数据) 文章目录 一、加载宾馆分布数据二、绘制热度图一、加载宾…

机器学习(十六):决策树

全文共18000余字&#xff0c;预计阅读时间约36~60分钟 | 满满干货&#xff0c;建议收藏&#xff01; 一、介绍 树模型是目前机器学习领域最为重要的模型之一&#xff0c;同时它也是集成学习中最常用的基础分类器。 与线性回归、逻辑回归等算法不同&#xff0c;树模型并不只是…

Web3.0:重新定义数字资产的所有权和交易方式

随着区块链技术的发展和应用&#xff0c;数字资产的概念已经逐渐深入人心。数字资产不仅包括加密货币&#xff0c;还包括数字艺术品、虚拟土地、游戏道具等各种形式的数字物品。然而&#xff0c;在传统的互联网环境下&#xff0c;数字资产的所有权和交易方式往往受到限制和约束…

Java 常用的重构技巧指南 v1.0

前段时间&#xff0c;leader 在 review 代码的时候发现了代码中 存在的一部分的问题&#xff0c;导致 代码的复杂度太高了&#xff0c;包括大部分的sql 都是属于慢sql &#xff0c;还是在建立了索引的情况下 , 代码的流程过于臃肿&#xff0c;而且本人编码的习惯&#xff0c;习…

Zookeeper集群 + Kafka集群 + Filebeat + ELK

目录 一&#xff1a;Zookeeper 概述 1、Zookeeper 定义 2、Zookeeper 工作机制 3、Zookeeper 特点 4、 Zookeeper 数据结构 5、 Zookeeper 应用场景 6、 Zookeeper 选举机制 &#xff08;1&#xff09;第一次启动选举机制 &#xff08;2&#xff09;非第一次启动选举机制…