我有这段代码:
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方法是否是线程安全的,因为每个实例成员函数都是线程安全的?或者在这里会产生异常吗?我看到一个使用锁的示例单例代码,我真的需要吗?
答案 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
}
}
换句话说 - 让核心框架为您管理锁定,互斥和易失性内容。