2011-03-17 189 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