2011-03-17 99 views
0

我有一个静态的DataLibrary类实现了单例模式。C#线程静态变量

 public static FacilityRepository FacilRepo 
     { 
      get 
      { 
       if (_facilRepo == null) 
       { 
        _facilRepo = new FacilityRepository(Authenticated.UserId); 
        if (Authenticated.FacKey.Length > 0) 
        { 
         foreach (var fac in _facilRepo) 
          fac.IsSelected = (fac.FacilityKey == Authenticated.FacKey);       
        } 
       } 
       return _facilRepo; 
      } 
     } 

private static FacilityRepository _facilRepo; 

当使用Task.Factory.StartNew的FacilityReposity被重建多次,我怎样才能避免这种情况我访问此从不同的线程。

+0

如果您同时创建许多新线程,并且它们都尝试访问FacilRepo属性,则可能是因为该属性没有锁定。看看http://en.csharp-online.net/Singleton_design_pattern%3A_Thread-safe_Singleton(在底部) – WiseGuyEh 2011-03-17 15:03:18

回答

9

我不认为你实际上在这里有一个线程局部变量 - 你刚刚得到一个竞争条件,因为你没有正确实现单例模式。

我有一个page about the singleton pattern它提供了一些更好的选择。 (特别是,由于您使用的TPL您必须使用.NET 4.0,所以Lazy<T>选项,绝对是一个竞争者。)

+0

+1这是快!我不敢相信我花了整整3分钟找到你的文章... – gideon 2011-03-17 15:08:14

+0

优秀的文章!!!!谢谢 。只要它让我多出4分钟,我就会接受你的回答。 – Wegged 2011-03-17 15:11:37

0

如果多个线程同时访问你的财产的第一次就会发生这种情况,以前_facilRepo是初始化。你必须锁定初始化代码:

private static object _facilRepoLock = new object(); 
public static FacilityRepository FacilRepo 
{ 
    get 
    { 
     if (_facilRepo == null) 
     { 
      lock (_facilRepoLock) 
      { 
       if (_facilRepo == null) 
       { 
        _facilRepo = new FacilityRepository(Authenticated.UserId); 
        if (Authenticated.FacKey.Length > 0) 
        { 
         foreach (var fac in _facilRepo) 
          fac.IsSelected = (fac.FacilityKey == Authenticated.FacKey); 
        } 
       } 
      } 
     } 
     return _facilRepo; 
    } 
} 

private static FacilityRepository _facilRepo; 
+2

没有变量是易变的,我不确定这是真正的线程安全。与使用双重检查锁定相比,实现线程安全有更简单的方法。 – 2011-03-17 15:05:00

+0

啊,有趣..我以前不知道..你的文章让人大开眼界:) – 2011-03-17 15:10:54