-1

我有这个代码:

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 方法是否是线程安全的,因为每个实例成员函数都是线程安全的?或者任何东西都会在这里产生异常?我看到一个使用锁的示例单例代码,我真的需要吗?

4

6 回答 6

3

你这里有很多问题...

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

如果两个线程同时请求该属性,那么它们都可以找到m_instance== null to betr​​ue`,返回两个不同的 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() 是线程安全的,我们不知道它在做什么。

于 2013-08-05T14:47:22.720 回答
2

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

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

于 2013-08-05T14:49:24.680 回答
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()本身不是线程安全的。它仍然可以从不同的线程调用,例如访问其他类的字段和属性。方法是否在单例实例中并不重要。您应该在这里使用其他机制来确保线程安全。

于 2013-08-05T14:51:17.717 回答
1

该代码没有任何同步,没有任何锁定机制就不是线程安全的。唯一的线程安全代码是具有同步机制的代码。

于 2013-08-05T14:37:56.933 回答
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 ...

于 2013-08-05T14:42:44.187 回答
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
    }
}

换句话说 - 让核心框架为您管理锁定、互斥和易失性的东西。

于 2013-08-05T14:59:11.667 回答