为什么这个单例构造代码不是线程安全的?

odi*_*seh 5 design-patterns thread-safety

在这段代码中,为什么写成"非线程安全"?谢谢

class Singleton
{
  private static Singleton _instance;

  // Constructor is 'protected'
  protected Singleton()
  {
  }

  public static Singleton Instance()
  {
    // Uses lazy initialization.
    // **Note: this is not thread safe.**
    if (_instance == null)
    {
      _instance = new Singleton();
    }

    return _instance;
  }
}
Run Code Online (Sandbox Code Playgroud)

sha*_*oth 24

如果两个线程同时运行if (_instance == null)检查,而没有创建单例实例,则它们都会尝试调用new以创建单例实例并将对它们的引用存储到同一个变量中.

由于它们将尝试存储的引用将在线程之间共享,因此该操作不是线程安全的.也可能会发生创建单个类的两个实例将破坏程序.

  • +1,但值得一提的是,它们甚至不必同时运行.单个核心处理器上的上下文切换**在**Thread1检查了条件之后**但是在它指定`instance`之前**会让Thread2创建Singleton.当Thread1重新开始播放时,它将继续播放,并创建并分配Singleton. (11认同)

RPM*_*984 8

因为Singleton不提供_instance属性的互斥.

使用来实现线程安全:

Object thisLock = new Object();

public static Singleton Instance()
{
    lock (thisLock)
    {
        if (_instance == null)
        {
           _instance = new Singleton();
        }
    }

    return _instance;
}
Run Code Online (Sandbox Code Playgroud)

这个例子是C# - 我不知道你正在使用哪种编程语言.

http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.90).aspx


Mar*_*oon 5

基于RPM1984的答案:

我使用以下锁定对象: object thisLock = typeof( Sinlgeton );

要不就

...
lock( typeof( Singleton ) )
{
   ...
}
Run Code Online (Sandbox Code Playgroud)

对于你们中的表现:

public Singleton getInstance()
{
    // the first query may save a performance-wise expensive lock - operation
    if ( null == _instance )
    {
       lock ( typeof( Singleton ) )
       {
          if ( null == _instance )
          {
             _ instance = new Singleton()
          }
       }
    }

    return _instance;
}
Run Code Online (Sandbox Code Playgroud)

BTW:这被称为双锁单例模式.

  • -1:双锁策略是好的,但你永远不应该锁定类的类型.私有的本地静态对象是最好的.查看第一个注释http://msdn.microsoft.com/en-us/library/system.type.aspx (2认同)