这个单例实例成员线程是否安全?

时间:2013-08-05 14:36:55

标签: c# multithreading

我有这段代码:

public class Singleton
{
    private static Singleton m_instance;
    private Singleton()
    {    

    }

    public static Singleton Instance
    {
        get
        {
            if (m_instance == null)
            {
                m_instance = new Singleton();
            }
            return m_instance;
        }
    }

    public void CallMe()
    {
       // is this function thread safe ? 
    }
}

CallMe方法是否是线程安全的,因为每个实例成员函数都是线程安全的?或者在这里会产生异常吗?我看到一个使用锁的示例单例代码,我真的需要吗?

6 个答案:

答案 0 :(得分:3)

你这里有多个问题......

首先,Instance属性不一定是线程安全的。

如果两个线程同时请求该属性,那么他们可以同时找到m_instance == null to be true`,返回两个不同的Singleton实例,但只有一个最终会被分配未来的电话。

您需要实施

private static lockObject lock = new Object();

public static Singleton Instance
{
    get
    {
      if (m_instance != null) return m_instance;
      lock (lockObject)
            {
                if(m_instance != null) return m_instance;
                return m_instance = new Singleton();
            }
    } 
}

或者只是在静态构造函数中实例化m_instance。

其次,即使第一个问题得到解决,你也不能说CallMe()是线程安全的,我们不知道它在做什么。

答案 1 :(得分:2)

首先,您的Instance方法不是线程安全的。如果它同时被调用两次,它将返回两个不同的实例(因此打破单例模式)。

如果没有看到它的代码,就不可能知道CallMe是否是线程安全的。

答案 2 :(得分:1)

没有任何同步的代码在没有任何锁定机制的情况下不是线程安全的。唯一的线程安全代码是具有同步机制的代码。

答案 3 :(得分:1)

有单锁变体,具有双重锁定或嵌套类。但.NET 4.0及更高版本中最简单的解决方案是使用Lazy属性:

public class Singleton
{
    private static Lazy<Singleton> m_instance = new Lazy = new Lazy<Singleton>();
    private Singleton()
    {    

    }

    public static Singleton Instance
    {
        get
        {
            return m_instance.Value;
        }
    }

    public void CallMe()
    {
       // now its threadsafe
    }
}

Lazy构造函数也可以选择创建函数或LazyThreadSafetyMode枚举

Singleton.Instance现在是线程安全的,但不是CallMe()本身。它仍然可以从差异线程调用,例如访问其他类的字段和属性。在单例实例中该方法是否存在并不重要。您应该使用其他机制来确保线程安全。

答案 4 :(得分:0)

扩展丹尼尔的回答:

private readonly object _threadLock = new Object();

public void CallMe() {
   // whatever happens here is not thread-safe

   lock(_threadLock) {

      // this is the simplest form of a locking mechanism
      // code within the lock-block will be thread-safe
      // beware of race conditions ...

   }
}

Jon Skeet是.Net的权威,专注于C#。以下是他对线程安全单例实例化的分析的链接:C# in Depth: Implementing Singleton ...

答案 5 :(得分:0)

这就是我如何使CallMe线程安全:

public class Singleton
{
    private static readonly Singleton instance = new Singleton();

    private Singleton()
    {    

    }

    public static Singleton Instance { get { return instance; } }

    public void CallMe()
    {
       // Thread Safe
    }
}

换句话说 - 让核心框架为您管理锁定,互斥和易失性内容。