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

+2

这可能是有用的:http:// csharpindepth。com/articles/general/singleton.aspx –

+0

它在技术上并不是线程安全的,但该方法什么都不做,所以不确定这一点。 – EkoostikMartin

+2

[你称之为“线程安全”的东西是什么?](http://blogs.msdn.com/b/ericlippert/archive/2009/10/19/what-is-this-thing-you-call-thread -safe.aspx)“线程安全”本身并不意味着什么。具体来说,你想确保代码的正确性?我们需要知道这些(以及更多关于如何实施该方法)以了解这种方法是否适用于您的情况。 – Servy

回答

1

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

+0

你能解释一下吗?它只是一个非静态实例成员吗?并没有什么共享accross .. –

+0

@VibinKesavan你说'私人静态Singleton m_instance;'是非静态的? – GolfWolf

+3

静态并不意味着这个类的方法是同步的。 –

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 ... 

    } 
} 

乔恩斯基特是.NET中的权威,以C#。下面是他的线程安全的单实例的分析链接:C# in Depth: Implementing Singleton ...

+0

您如何知道该方法的全部内容需要同步?如果没有对共享状态的访问,则不需要在该方法内锁定任何内容。 – Servy

+0

@Servy:我不知道:) ......这只是一个基于OP问题的简单示例,并没有提供任何进一步的细节。你的问题是有效的,只有OP可以回答。 – IAbstract

3

您在这里有多种问题...

首先使用实例属性不一定是线程安全的。

如果两个线程同时请求属性,那么他们都可以同时发现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()是线程安全的,我们不知道它在做什么。

+0

我找到了你,但CallMe在这里没有解决。为什么我需要锁定那里.. –

+0

@VibinKesavan不,但你会使用'Singleton.Instance.CallMe()'和'Instance'部分会遭受问题一,你可以有两个不同的实例调用'CallMe ()'。 –

+1

@VibinKesavan你知道线程安全的意思吗? CallMe可能或不可能是线程安全的,具体取决于它是否使用可以在线程之间共享的外部状态变量。你没有向我们展示CallMe的代码,所以我们不能说它是否是线程安全的。 –

2

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

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

+0

我同意你的第一点,但告诉我CallMe是线程安全与否,如果不是?我怎么能证明这一点 –

+0

@VibinKesavan“线程安全”本身并不意味着什么。你需要更具体地说明你期望它做什么,不做什么。当你说“线程安全”时,你的意思是什么?此外,如果没有实施该方法,或者至少对其做了什么或不做什么类型的事情有所了解,我们就不能进一步评论。 – Servy

1

有双重锁定或嵌套类singletone变种。但在.NET 4.0及以上的最简单的方法是使用延迟属性:

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 
    } 
} 

懒惰的构造函数有必要时也创造功能,或LazyThreadSafetyMode枚举

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

+0

CallMeMethod怎么样? “实例”方法现在是线程安全的,但不打电话给我,我猜 –

+0

更容易,只是写:'私人静态Singleton m_instance =新Singleton();'。它代码少,同样也是线程安全的。 – Servy

+0

@Servy:是的。这已经足够了,但是如果你在.NET 2.0或者更高版本上执行它,它的行为有点依赖 –

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 
    } 
} 

换句话说 - 让核心框架为您管理的锁定,互斥体和挥发性的东西。

相关问题