这个代码线程安全吗?

时间:2011-08-10 08:20:14

标签: c# thread-safety

我想知道这段代码是否是线程安全的,以及为什么不是这种情况。

    static IMyInterface _myinterface;
        public static IMyInterface someStuff
        {
            get
            {
                if (_myinterface== null)
                {
                    _myinterface= MyServiceLocator.GetCurrent().GetInstance<IMyInterface>();
                }

                return _myinterface;
            }
        }

谢谢!

7 个答案:

答案 0 :(得分:4)

正如其他人所说,事实并非如此。但是,有一些选项可以使它从普通锁定或双重检查模式进行线程安全appart - 这不能保证在CLR的所有(可能的)实现上都有效。

另请注意,除非您期望高争用,否则实际上不需要双重检查锁定,并且几乎没有什么区别。错误相对容易(参见其中一个答案中的其他(最初)错误的实现作为一个很好的例子)。

有关详情,请参阅主题Jon Skeet's article

答案 1 :(得分:1)

对我而言,事实并非如此。 因为在唯一的方法之间确定是在它上面加一个锁。它可能有两个线程进入if语句!

http://msdn.microsoft.com/en-us/library/c5kehkcz%28v=vs.80%29.aspx

答案 2 :(得分:1)

没有。你需要使用锁。

private static readonly object m_lock = new object();
private static IMyInterface _myinterface;

public static IMyInterface someStuff
{
    get
    {
        lock(m_lock)
        {
           if (_myinterface == null)
           {
             //create instance
           }

           return _myinterface;
        }            
    }
}

答案 3 :(得分:1)

不,不,你想做更像这样的事情。请注意_myinterface==null上的双重检查。这是因为在您第一次检查后,另一个线程可能已经在锁中创建它。因此,一旦锁定,您需要仔细检查。

static IMyInterface _myinterface;
private static object lockObj = new object();
public static IMyInterface someStuff
{
   get
   {
      if (_myinterface== null)
      {
         lock(lockObj)
         {
            if (_myinterface== null)
            {             
                _myinterface= MyServiceLocator.GetCurrent().GetInstance<IMyInterface>();
            }
         }
      }
      return _myinterface;
}

答案 4 :(得分:1)

这不是因为可能有多个初始化线程会同时尝试访问单例。

这可行:

    static object _lock=new object(); 
    static IMyInterface _myinterface;
    public static IMyInterface someStuff
    {
        get
        {
            lock (_lock) {
                if (_myinterface== null)
                {
                    _myinterface= MyServiceLocator.GetCurrent().GetInstance<IMyInterface>();
                }
            }
            return _myinterface;
        }
    }

答案 5 :(得分:0)

不,不是。

为什么?

两个来自someStuff的来电已经超过if(_myInterface null),但被中断_myInterface = MYServiceLoc...。第二个线程完全进入并在进入睡眠状态之前完成。第二个醒来,分配到_myInterface。

两者最终调用MyServiceLocator ... GetInstance(),都分配给_myInterface,两者都可以为_myInterface返回不同​​的值。

答案 6 :(得分:0)

不,可能会发生两个不同的线程实例化不同的实例,并且会删除之前保存的_ myInterface的值。

想象一下,线程#1进入了if

if (_myinterface== null)                 
{
 // ... here

和线程#2也读取_ myinterface并进入此块,此时Thread#1实例化了对象并更新了_myinterface的引用。 但同时Thread#2已缓存_myinterface的值(它为NULL)并创建一个由Thread#1存储的新对象和ower写值。

通过lock()包装getter,这样只有一个线程可以输入(参见关于双重锁定的其他答案)