以下代碼將從網站調用,因此在非靜態類中有一個靜態字典對象需要線程安全。基本上,代碼的目的是封裝邏輯並維護存儲在CounterContainer實例中的perfmon計數器的生命週期。構造函數被稱爲傳入instanceName。構造函數需要檢查該實例名稱的CounterContainer是否已被定義並存儲在字典中。如果是這樣,它可以(並且必須)使用該實例。如果不是,它會創建一個CounterContainer實例,將其存儲在字典中,然後使用該實例。要使用的CounterContainer實例存儲在一個非靜態成員中,因此線程安全。這是鎖定線程安全的正確對象嗎?
作爲使用靜態字典的唯一地方是在構造函數中,它讓我覺得在它將被訪問期間鎖定字典是安全的嗎?這是否會導致任何不可預見的問題,如阻塞/死鎖?我什麼都看不到,但過去並沒有太多需要考慮這種事情。我也考慮過lock(this):但我不認爲這樣會工作,因爲它只會鎖定被創建的PerformanceCounters的實例,而不是基礎的靜態字典(所以不會是線程安全的)。
namespace ToolKit
{
using System;
using System.Diagnostics;
using System.Collections.Generic;
public class PerformanceCounters : IPerformanceCounters
{
private static Dictionary<string, CounterContainer> _containers = new Dictionary<string, CounterContainer>();
private CounterContainer _instanceContainer;
public PerformanceCounters(string instanceName)
{
if (instanceName == null) throw new ArgumentNullException("instanceName");
if (string.IsNullOrWhiteSpace(instanceName)) throw new ArgumentException("instanceName");
// Is this the best item to lock on?
lock (_containers)
{
if (_containers.ContainsKey(instanceName))
{
_instanceContainer = _containers[instanceName];
return;
}
_instanceContainer = new CounterContainer(instanceName);
_containers.Add(instanceName, _instanceContainer);
}
}
public void Start()
{
_instanceContainer.AvgSearchDuration.Start();
}
public void FinishAndLog()
{
_instanceContainer.SearchesExecuted.Increment();
_instanceContainer.SearchesPerSecond.Increment();
_instanceContainer.AvgSearchDuration.Increment();
}
}
}
你有沒有考慮過使用ConcurrentDictionary類?那麼你不必擔心它 - 也可以重複到這個問題:http://stackoverflow.com/questions/440957/c-concurrency-locking-and-dictionary-objects – BrokenGlass 2010-09-29 13:07:40
@BrokenGlass:對不起,我錯過了,是的,他們幾乎完全相同的情況。在沒有聽說過ConcurrentDictionary類之前,它也被提出來作爲對此的迴應。 – 2010-09-29 17:30:14