我有一個多線程的C#應用程序。有一個字典可以同時從N個不同的線程訪問。來電的99%都來自線程A,其餘都是從B,C,...C#線程性能,一線程99%的時間
現在,我只是鎖定在每次訪問字典。但它看起來很浪費,因爲99%的時間我叫鎖,線程A已經鎖定。
這樣做會更有效嗎?
也許某些類型的.Begin和.End調用可能需要線程B,C ...,然後線程A只需檢查每個調用中的一個位以查看是否有其他線程正在使用詞典。有沒有人有這樣的線程安全的方式實現的代碼示例?
我有一個多線程的C#應用程序。有一個字典可以同時從N個不同的線程訪問。來電的99%都來自線程A,其餘都是從B,C,...C#線程性能,一線程99%的時間
現在,我只是鎖定在每次訪問字典。但它看起來很浪費,因爲99%的時間我叫鎖,線程A已經鎖定。
這樣做會更有效嗎?
也許某些類型的.Begin和.End調用可能需要線程B,C ...,然後線程A只需檢查每個調用中的一個位以查看是否有其他線程正在使用詞典。有沒有人有這樣的線程安全的方式實現的代碼示例?
您需要仔細檢查您的分析器數據。
兩個監視器和RWLSlim不會真正「硬鎖」(如在下拉到OS原語),除非有一個實際的競爭;在所有其他情況下將使用Interlocked,並且相對最小的性能影響(除緩存刷新外)。
性能方面,RWLockSlim的創建成本相對較高,而且比Monitor要貴一些。它的優點是允許多個讀者和一個作家。
如果您看到硬盤鎖顯示出來,那麼你有實際的競爭,在這種情況下,你可能說99%/ 1%/ 1%/ 1%/ ...比率不能反映現實。
正如前面提到的海報,你應該exmaine使用的塔彭定康 - 在大多數情況下,你偶爾也會寫入和讀取大量,否則系統的一致性有些難以enforfce。如果是這種情況,RWlockSlim應該消除不必要的爭用。
底線:這一切都取決於你正在嘗試做的事情 - 在什麼這本字典是如何被訪問。有時候擴展鎖以防止佔用過多的鎖是有意義的,而在某些情況下(甚至非常罕見),在嘗試擊中「真正」鎖之前,您可能需要使用「無鎖」類型的無鎖基元。
也許如果你告訴了我們更多關於這個場景的信息,我們可以幫助更好。
你如何執行鎖定。對於閱讀而言,您不需要像「更新」一樣以「硬」的方式鎖定其他線索。無論哪種方式,讀取操作都會變得更鬆散。我建議尋找到ReaderWriterLockSlim
(除非你已經在使用它):
class DictionaryHolder
{
private IDictionary<int, string> _data = new Dictionary<int, string>();
private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
public void Update(int key, string value)
{
_lock.EnterWriteLock();
try
{
_data[key] = value;
}
finally
{
_lock.ExitWriteLock();
}
}
public string GetValue(int key)
{
_lock.EnterReadLock();
try
{
if (_data.ContainsKey(key))
{
return _data[key];
}
finally
{
_lock.ExitReadLock();
}
}
}
這將允許多個線程從字典「在同一時間」閱讀,在更新時,它阻止來自其他線程訪問。
謝謝,我在考慮ReaderWriterLockSlim。任何想法如何將「_lock.EnterReadLock()」的性能與「Monitor.Enter」進行比較?我從來沒有用過它。 – 2009-08-06 20:45:12
我無法對獲取鎖的性能發表評論,但'_lock.EnterReadLock'的優勢在於不會鎖定其他線程也需要讀者鎖定。它只是在更新操作的周圍(由'_lock.EnterReadLock'保護),你有一個鎖會阻止其他線程訪問字典。 – 2009-08-06 20:53:39
你不應該擔心這個,除非分析器告訴你,你是花了很多的Monitor.Enter和公司的時間 - 在一般情況下,獲得你已經持有非競爭鎖或鎖是一個非常快的操作,必須性能與您建議的位檢查類似。鎖定操作通常只有在由於爭用而必須阻止時纔會很慢。
謝謝。不幸的是,根據ANTS分析器,鎖定呼叫佔用了我在該函數中花費的大部分時間。 – 2009-08-06 20:47:28
ReaderWriterLockSlim在有很多讀者和很少的作者時會有所幫助。但是,根據以下鏈接,ReaderWriterLockSlim的個人操作性能似乎比Monitor差:A Performance Comparison of ReaderWriterLockSlim with ReaderWriterLock。
你可以嘗試的一個選擇是與Interlocked操作一起玩Event對象來同步線程。但是,你也應該測量這種方法的性能。
嘗試在.NET中使用System.Collections.Concurrent.ConcurrentDictionary
4.0
這是線程安全的設計
這是.NET 4的一個很好的選擇。你知道它的實現嗎?我想知道它是如何執行的,而不是鎖定對常規字典的所有訪問。 – 2010-10-05 12:59:54
System.Collections.Concurrent成員是內置線程安全的。沒什麼特別的。例如,使用帶有多個線程的併發隊列,並且無需考慮任何事情就調用'Enqueue'或'Dequeue'。如果您想了解詳細信息,請在所需的庫上使用Reflector來實現。根據我的經驗,速度很好。 – Xaqron 2010-10-05 17:24:05
參見http://stackoverflow.com/questions/157933/whats-the-best-way-of-implementing-a -thread-safe-dictionary-in-net – 2009-08-06 20:30:46