昨天我問了一個關於這個問題的問題,並得到了很多有用的反饋(謝謝!),但我認爲我沒有給出足夠的信息 - 因此,另一個問題。無法安全鎖定ConcurrentDictionary的值
我有兩個線程同時讀取兩個文件。他們將來自這些文件的信息放入兩個ConcurrentQueue中。另外兩個線程隨之出現,從ConcurrentQueues中取出項並將項放入單個ConcurrentDictionary中。更新字典中的項目時,線程可能必須創建一個新對象,或者只是通知當前對象有更多信息進來。在後一種情況下,有時會發生漫長的掃描。有時候,在這次掃描之後,對象說它可以將其刪除(作爲一種節省內存的嘗試),並且該線程將其從字典中移除。
我現在的(碎)下面的代碼:
string dictionaryKey = myMessage.someValue;
Monitor.Enter(GetDictionaryLocker);
DictionaryObject currentObject = myConcurrentDictionary.GetOrAdd(dictionaryKey, new DictionaryObject());
// we can be interrupted here
lock (currentObject)
{
Monitor.Exit(GetDictionaryLocker);
//KeyNotFoundException is possible on line below
if (myConcurrentDictionary[dictonaryKey].scan(myMessage)) // Scans the message - returns true if the object says its OK to remove it from the dictionary
{
DictionaryObject temp; // It's OK to delete it
if (!queuedMessages.TryRemove(ric, out temp)) // Did delete work?
throw new Exception("Was unable to delete a DictionaryObject that just reported it was ok to delete it");
}
}
什麼情況是這樣的:
由於發現我想在字典中的對象之間:
DictionaryObject currentObject = myConcurrentDictionary.GetOrAdd(dictionaryKey, new DictionaryObject());
,然後鎖定在該對象:
lock (currentObject)
,線程可以interuppted,所以那裏有一個機會,另一個線程的時候我避開試圖在這裏訪問它刪除的對象了字典:
if (myConcurrentDictionary[dictonaryKey].scan(myMessage))
這就導致KeyNotFoundException。我需要一些自動鎖定對象的方法。
正如我所說的,我昨天得到了一些建議,但我不明白他們
- 其中一張海報提到,我應該嘗試首先從字典中刪除項目,因爲這是一個我可以如何使用使用ConcurrentDictionary進行原子操作,然後重新添加它們。然而,我不確定我會如何向其他線程表明它應該等待該項目被重新添加,而不是僅僅考慮它的缺失值並創建它。
- 另一個海報帶來了
Threading.Interlocked.CompareExchange
,我可以用它來標記該對象正在使用中。但我不知道如何處理正在使用的對象的情況 - 我將如何等待?
我有一些限制:我必須按順序處理ConcurrentQueues,所以我不能放棄將對象放在字典中,或稍後再回來 - 我需要阻止。該詞典可能包含500,000個或更多項目,所以我確實需要ConcurrentDictionary的O(1)查找時間。
任何想法?很抱歉的長期職位
感謝,
弗雷德裏克
更新現有的文章而不是創建新的文章會更好嗎?這樣,所有有用的提示將會失去幫助你的新人。 – 2010-10-27 10:34:04
對不起,大衛,這個網站的新手 - 在另一個線程的海報要求我發佈一個新的線程與額外的信息。鏈接在這裏:http://stackoverflow.com/questions/4025428/cant-safely-lock-a-value-of-a-concurrentdictionary – Frederik 2010-10-27 10:36:36