java用sychronized实现的单例模式两种实现方式有什么区别?

二哥的博客 二哥的博客 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
看设计模式的时候,网上有代码说,在考虑多线程的时候,用sychronized做同步的时候必须将getInstance和new操作分开,否则会有可能出错;也就是讲下面第一段代码改为第二段:

public class SingletonTest {

private static SingletonTest instance = null;

private SingletonTest() {
}


public static Singleton getInstance() {
if (instance == null) {
synchronized (instance) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
​​ }
​
}


改成:

public class SingletonTest {


private static SingletonTest instance = null;

private SingletonTest() {
}

private static synchronized void syncInit() {
if (instance == null) {
instance = new SingletonTest();
}
}

public static SingletonTest getInstance() {
if (instance == null) {
syncInit();
}
return instance;
}
}

​

网上的理由是:
在Java指令中创建对象和赋值操作是分开进行的,也就是说instance = new Singleton();语句是分两步执行的。但是JVM并不保证这两个操作的先后顺序,也就是说有可能JVM会为新的Singleton实例分配空间,然后直接赋值给instance成员,然后再去初始化这个Singleton实例。这样就可能出错了,我们以A、B两个线程为例:

a>A、B线程同时进入了第一个if判断

b>A首先进入synchronized块,由于instance为null,所以它执行instance = new Singleton();

c>由于JVM内部的优化机制,JVM先画出了一些分配给Singleton实例的空白内存,并赋值给instance成员(注意此时JVM没有开始初始化这个实例),然后A离开了synchronized块。

d>B进入synchronized块,由于instance此时不是null,因此它马上离开了synchronized块并将结果返回给调用该方法的程序。

e>此时B线程打算使用Singleton实例,却发现它没有被初始化,于是错误发生了。



看了很不理解,改进的方法不是也有同样的问题? 两者的区别在哪儿?(对面同步就能保证instance一定是实例化之后才被使用么?)
...全文

相关推荐

JAVA中常用的数据结构

另外,Vector类是线程同步的(sychronized),这也是Vector和ArrayList的一个重要区别。

qq_39292819

java并发编程面试题分享给需要的同学.docx

并发编程并发编程夺命连环问JUC什么是死锁?如何避免死锁?什么是可重入锁?CountDownLatchCyclicBarrierSemaphore什么是自旋锁(CAS,compare and swap

飞翔的佩奇

leetcode下载-study:学习笔记

leetcode下载目录操作系统虚拟内存与物理内存转化CPU调度方式进程栈大小进程与线程区别线程状态网络TCP四次挥手SYNFlood如何避免HTTP头部字段HTTP请求方式AIOOSI七层模型ARP

抹蜜茶

Sychronized和ReentrantLock的区别

sychronized锁的是对象,锁信息保存在对象头中,ReentrantLock通过代码中int类型的state标识来标识锁的状态。sychronized会⾃动的加锁与释放锁,ReentrantLock需要程序员⼿动加锁与释放锁。sychronized的底层是JVM层⾯的锁,ReentrantLock是API层⾯的锁。sychronized是⾮公平锁,ReentrantLock可以选择公平锁或⾮公平锁。锁的状态(偏向锁、轻量级锁、重量级锁)由 JVM 自动管理。默认是非公平锁(不保证线程获取锁的顺序)。

EthanMilk

YOLO26算法工业车间与城市道路安全标识及交通标志目标检测+训练好的模型+260张数据集+pyqt可视化界面.zip

附训练好的 YOLO 权重与 PyQt 可视化检测界面,页面底部含可视化效果预览,毕设/课设开箱即用。 【数据集概况】 · 检测类别(中文):[安全标识(safety), 交通标志(traffic)] · 训练集:240 张 · 验证集:10 张 · 测试集:10 张 · 总计:260 张 该数据集精准聚焦于工业生产环境与城市道路交通场景,旨在为高危作业区域的安全警示系统及道路通行管理提供可靠视觉识别支持。通过采集真实工作现场与道路环境中的关键标识,该数据集有效支撑了对人员行为规范提示与交通状态预警的自动化感知需求,具备显著的工程实用价值与行业落地潜力。... 【训练曲线与评估图】 【模型训练配置】 参数 | 值 模型 | yolo26n 训练轮数 | 100 epochs 输入尺寸 | 640x640 批次大小 | 24 优化器 | auto 初始学习率 | 0.01 训练设备 【关键指标汇总】 训练了 67 个 epoch,最终轮指标: 指标 | 数值 mAP50 | **0.7278** mAP50-95 | 0.6630 Precision | 0.7294 Recall | 0.7273 train/box_loss | 0.7483 train/cls_loss | 0.6857 val/box_loss | 0.6823 val/cls_loss | 1.8035 【训练过程分析】 67 轮训练后 mAP50 为 0.7278,模型基本收敛但还有提升余地。Loss 曲线下降正常,后期趋于平缓。mAP50-95 为 0.6630,定位精度尚可。 【模型性能评估】 Precision 0.7294、Recall 0.7273,精度高于召回,存在一定漏检。多类检测中,不同类别性能可能有差异,需关注... 使用场景:毕业设计、课程设计、深度学习入门、工业场景落地验证。

guo_xiao_xiao_
评论 9
收藏 已收藏
分享
返回顶部
二哥的博客
Java 51,407 成员 86,126 内容