重学设计模式 - Double-Checked Locking模式

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

1、  意图

多线程中,创建线程安全的单件模式。

2、  问题

多线程中,Singleton模式并不总是正常工作的。

3、  解决方案

在检查到null或实例未创建之后进行“同步”,然后再检查一次,确保实例尚未创建

4、  效果

Singleton模式的变体,优化掉不必要的锁定,这种同步检查最多进行一次,因此不会成为瓶颈。

5、  实现

// .Net中通过MemoryBarrier 实现
public class MySingleton {
    private static object myLock = new object();
    private static MySingleton mySingleton = null;
    private static bool ready = false;
 
    private MySingleton() { 
    }
 
    public static MySingleton GetInstance() {
        if (!ready) { // 1st check
            lock (myLock) {
                if (!ready) { // 2nd (double) check
                    mySingleton = new MySingleton();
                    System.Threading.Thread.MemoryBarrier();    // fence
                    ready = true;
                }
            }
        }
        return mySingleton;
    }
}
// 使用C#关键字volatile实现,会降低效率
public class MySingleton {
    private static object myLock = new object();
    private static volatile MySingleton mySingleton = null;
 
    private MySingleton() { 
    }
 
    public static MySingleton GetInstance() {
        if (mySingleton == null) { // check
            lock (myLock) {
                if (mySingleton == null) { // double check, volatile ensures that the value is re-read
                    mySingleton = new MySingleton();
                }
            }
        }
        return mySingleton;
    }
}
// .net 4.0中可以使用Lazy<T>实现
public class MySingleton
{
    private static readonly Lazy<MySingleton> mySingleton = 
        new Lazy<MySingleton>(() => new MySingleton());
 
    private MySingleton()
    { }
 
    public static MySingleton GetInstance()
    {
        return mySingleton.Value;
    }
}



 

由浅入深讲解volatile volatile volatile 是一个类型修饰符。volatile 的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略 volatile 的特性 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。(实现可见性) 禁止进行指令重排序。(实现有序性) volatile 只能保证对单次读/写的原子性。i++ 这种操作不能保证原子性。关于volatile 原子性可以理解为把对volatile变量的单个读/写,看成是使用同一个锁对这些单 阅读详情

相关推荐

解决fortify扫描出的Code Correctness: Double-Checked Locking问题(java语言)

现有java代码如下: 。。。 if (fitz == null) {   synchronized (this) {     if (fitz == null) {       fitz = new Fitzer();     }   } } return fitz; 。。。 使用fortify扫描出Code Correctness: Double-Checked Lock

wypdao的专栏 6450

双重检查锁定(Double-Checked Locking

双重检查锁定是一种在多线程环境中用于懒初始化的优化方法,能够减少不必要的锁开销。虽然传统的双重检查锁定模式在某些情况下存在内存模型问题,但通过 C++11 提供的新特性如 std::atomic 和 std::call_once,我们可以更安全地实现这一模式,并确保线程安全性。

yao_tao11的博客 3251

Java中的双重检查锁(double checked locking

这文章写的很好,我看懂了,收获了。 原文地址https://www.cnblogs.com/xz816111/p/8470048.html 最初的代码 在最近的项目中,写出了这样的一段代码 private static SomeClass instance; public SomeClass getInstance() { if (null == instance) { ...

earthhour的专栏 1863

双重检查锁定(Double-Checked Locking)的问题和解决方案

读《Java并发编程的艺术》方腾飞、魏鹏、程晓明著。笔记 一、什么是双重检查锁定 为了提高性能,会延迟初始化某些类,在第一次使用的时候做类的初始化。为了保证多线程下的线程安全,一般会做安全同步。简单的方式就是如下: public class Singleton { private static Singleton instance; public synchronized Singleton getInstance() { if (instance == nu.

CrazyTiger的博客 1万+

Fortity 安全评测结果及解决方案一文全解

Fortity 安全评测结果及解决方案

2301_76354366的博客 6080

Double checked locking,两次检查的锁

最开始知道这个内容是在和室友聊天的时候发现的,它说国内某互联网公司中有一道笔试题,需要当场写出无锁队列的代码。当时对于这个概念还是一知半解,后来他说陈皓博客上有相关的内容,本着好学的精神就去一窥究竟:无锁队列的实现 基本思想是利用编译器或者语言提供的原子操作,CAS(compare and swap或者compare and set)。 bool compare-and-swap(Ad

Sands make life richful. 776

双重检查锁(double-checked locking

在软件工程中,双重检查锁(double-checked locking[1])是一种设计模式,通过在加锁前检查锁标志(criterion),可以减少加锁的开销。只有当标志显示需要的时候才...

felix021的专栏 4329

单例模式“双重检查锁定Double-Checked Locking”线程安全问题

几篇合集。 1 单例模式“双重检查锁定Double-Checked Locking”线程安全问题 https://blog.csdn.net/wabiaozia/article/details/84723899 2 主题:用happen-before规则重新审视DCL https://blog.csdn.net/wabiaozia/article/details/84727407 3 D...

ice-wee的专栏 4687

Double-Checked Locking失效问题

双重检查锁定失效问题,一直是JMM无法避免的缺陷之一.了解DCL失效问题, 可以帮助我们深入JMM运行原理.要展示DCL失效问题, 首先要理解一个重要概念- 延迟加载(lazy loading). 非单例的单线程延迟加载示例: class Foo {    private Resource res = null;    public Resource getResource() {      ...

Ken's Blog 257

Fortify 5.1漏洞整改方案(1)

很多企业对代码的安全性有着很高的要求,目前使用的较为多的扫描代码安全漏洞的工具为Fortify 5.1。以下为一些漏洞的解决方案,欢迎指正。 1.Password Management: Empty Password 1)简介:为密码变量指定空字符串绝非一个好方法。如果使用 emp...

chongweimei5390的博客 2288

双检锁/双重校验锁(DCL,即 double-checked locking)详细解析

单例模式是最常用的设计模式,并且双锁单例模式也是面试的常考题目。本文详细介绍了双锁单例模式,并总结了双锁单例模式的三个常考问题。

weixin_44214900的博客 1万+

单例模式 - 双重检查锁定(Double-Checked Locking

介绍单例模式、双重检查锁定(double-checked locking

qq_44960878的博客 4319

double-checked-locking(双重检查锁定)设计模式

在github上的java-design-patterns的项目中提到了double-checked-locking这种设计模式,解释如下: Double Checked Locking is a concurrency design pattern used to reduce the overhead of acquiring a lock by first testing the ...

qq_22158743的博客 1200

工作日记

工作日记 2017年 1 使用完毕后记得回收 list.clear(); list=null; 2 UPDATE products SET goods_number = goods_number+10 ORDER BYgoods_id DESC LIMIT 5,10 上面这句测试了是错误的,MYSQL的UPDATE语句不能更新限制从第几条到第几条! 3 MySQL SQL GROUP BY是如何...

weixin_30814329的博客 1164

高并发下双重检测锁DCL指令重排问题剖析

双重检查锁定(Double-Checked Locking)是一种并发设计模式,该模式减少了同步的开销,提高了执行效率。该模式通过两次检查锁定,确保被检查的代码的线程安全性。在第一次检查中,如果发现变量不满足条件,才进行加锁操作。然后在锁定的区块内再进行一次检查,如果仍不满足条件,才进行相关操作。指令重排是为了提高处理器性能,允许编译器和处理器调整指令的执行顺序。一旦保证最终执行结果与代码顺序执行的结果一致,即使没有按照代码原有的顺序执行也不影响。volatile是Java提供的一种轻量级的同步机制。

日拱一卒无有尽,功不唐捐终入海 1599

单例模式之DCL(Double-Checked Locking)

The "Double-Checked Locking is Broken" Declaration,单例模式之DCL的解读

于琦海 1521

常见线程安全问题之Double Checked Locking

最简单的解决方式是读操作也加锁,如果性能达不到要求,也可以像本节一样使用 volatile,但我个人不建议这么用,因为有太多细节需要考虑,可以使用 JUC 中的。问题不仅仅在于写的一方,即使 helper 被正确初始化并赋值,由于另一个线程所在的 CPU 可能会从缓存中读取 helper 的值,如果 helper 的新值还没有被更新到缓存中,则读取的值可能还是。因为 64 位的操作不是原子的,于是可能造成前后 32 位不是一起写入内存的,而另一个线程只读取先写入的 32 位,读到的结果不正确。

彩虹地带 1140
上一篇: 重新设计模式 - Singleton模式
下一篇: 重学设计模式 - Object Pool模式
方寸之间
博客等级 码龄19年 198粉丝 118原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值