编写线程安全的单件(Singleton)

本文探讨了在多线程环境下Singleton模式实现的问题,并提供了一种线程安全的解决方案。通过对比线程不安全的Singleton实现,展示了如何利用锁机制确保实例的唯一性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    最近在 Review 代码的时候,发现大量类似如下风格的单件(Singleton)类:

ExpandedBlockStart.gifContractedBlock.gif    /**//// <summary>
InBlock.gif    
/// 线程不安全的 Singleton
ExpandedBlockEnd.gif    
/// </summary>

None.gif    public class Singleton
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif{
InBlock.gif        
static private Singleton instance;
InBlock.gif        
InBlock.gif        
private Singleton()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//
InBlock.gif            
// TODO: Add constructor logic here
InBlock.gif            
//
ExpandedSubBlockEnd.gif
        }

InBlock.gif
InBlock.gif        
static public Singleton Instance
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if( instance == null )
InBlock.gif                    instance 
= new Singleton();
InBlock.gif                
return instance;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }

    乍一看还很经典,但细一推敲,却发现了问题:
    
    当多个线程同时调用 Singleton.Instance 属性的时候,每个线程都检测到 instance == null 为真,于是每个都会傻乎乎的创建一个新实例.这将导致最先创建的实例实效,只有最后创建的实例被保存在静态的 instance 中.虽然这在大多数情况下不会引发大问题,但一旦构造函数中有比较耗时的操作,则会造成程序逻辑上的错误.而这些通常都是隐藏得很深,而且很难复现的超级大Bug .所以,要小心哪,同志们!

    为了避免这种问题,我采用了下面的代码:

ExpandedBlockStart.gifContractedBlock.gif    /**//// <summary>
InBlock.gif    
/// 线程安全的 Singleton
ExpandedBlockEnd.gif    
/// </summary>

None.gif    public class ThreadSafeSingleton
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif{
InBlock.gif        
static private ThreadSafeSingleton instance;
InBlock.gif        
static private object syncObj = new object(); //用于线程同步
InBlock.gif

InBlock.gif        
private ThreadSafeSingleton()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//
InBlock.gif            
// TODO: Add constructor logic here
InBlock.gif            
//
ExpandedSubBlockEnd.gif
        }

InBlock.gif
InBlock.gif        
static public ThreadSafeSingleton Instance
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
lock( syncObj )  //使用 Monitor 同步
ExpandedSubBlockStart.gifContractedSubBlock.gif
                dot.gif{
InBlock.gif                    
if( instance == null )
InBlock.gif                        instance 
= new ThreadSafeSingleton();
InBlock.gif                    
return instance;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }

转载于:https://www.cnblogs.com/louisliu/archive/2006/02/17/332158.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值