2012-01-30 34 views
2

我有一個HashTable被多個線程訪問。例如讓我們看看三個線程:HashTable併發性

線程A確實Hash.Insert(「a」,new object());線程B做Hash.Insert(「b」,new object());線程C確實是Hash.Insert(「a」,new object());

由於種種原因,我不能使用鎖對整個哈希

我不關心順序或哪個對象將是在過程結束的哈希值。我唯一關心的不是通過從不同線程更新同一個單元而導致數據損壞。

我有什麼選擇?或者它不是問題,HashTable自己處理它並保持數據的完整性。從System.Collections.Concurrent命名空間

ConcurrentDictionary<string, object> Hash = new ConcurrentDictionary<string, object>(); 

+0

「由於某些原因,我無法在整個哈希上使用鎖定」您能否解釋該需求?它只是表現嗎? – CodesInChaos 2012-01-30 08:14:38

+0

@CodeInChaos可以同時有成千上萬的請求,所以我更擔心飢餓,因爲它可能獲得一個線程鎖定永遠不會獲得處理器時間... – 2012-01-30 08:26:02

+0

這是非常不可能的,你會遇到由於非FIFO處理鎖。請參閱http://stackoverflow.com/questions/961869/is-there-a-synchronization-class-that-guarantee-fifo-order-in-c。用於確保FIFO排序的同步對象,這將防止飢餓。 – 2012-01-30 23:04:58

回答

5

你可以考慮使用類似的東西。

+0

我想過,但這取決於如何實現ConcurrentDictionary。它是否鎖定整個哈希?還是更復雜? – 2012-01-30 08:11:25

+0

@Amit我很確定實現是無鎖的,但這當然只是一個實現細節。但是無法直接觀察無鎖和鎖定實現之間的區別,除非無鎖通常更快。 – CodesInChaos 2012-01-30 08:13:40

+0

從快速查看反射器看來,併發字典似乎使用桶鎖,它似乎有幾個鎖,每個單元格的數量都會得到一個鎖。希望它足夠好 – 2012-01-30 08:21:04

3

ConcurrentDictionary應該爲你工作。它不是無鎖的,但它不會「鎖定整個散列」,除非在某些情況下。

它使用兩個集合,一個鎖數組和一個散列桶集合。
可以通過設置併發級別來控制鎖定桶的數量,並且可以通過設置初始容量來控制哈希桶的初始數量。 (這些都是構造函數參數)。

鎖陣列中的每個存儲桶使用簡單的模數散列來覆蓋幾個(至少有一個是真正的)散列存儲桶。

唯一倍併發字典鎖定所有的鎖桶是:

  1. 當調整大小的散列桶。
  2. 閱讀公鑰屬性時。
  3. 閱讀公共值屬性時。
  4. 閱讀公共計數屬性時。
  5. 閱讀公共IsEmpty屬性時。
  6. 當調用清除()時。
  7. 序列化時。

除了調整大小這些都是很容易避免的。

如果您可以預測字典中的最大項目數,則可以避免調整大小。