昨天我问了一个关于这个问题的问题,并得到了很多有用的反馈(谢谢!),但我认为我没有给出足够的信息 - 因此,另一个问题。无法安全锁定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