昨天我问了一个问题,并得到了很多有用的反馈(谢谢!),但我认为我在这个问题上提供的信息不足-因此,我提供了另一个信息。

我有两个同时读取两个文件的线程。他们将这些文件中的信息放入两个ConcurrentQueues中。然后再出现另外两个线程,从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)

,该线程可以插入,因此在我尝试在此处访问它时,另一个线程有可能将该对象从字典中删除:
if (myConcurrentDictionary[dictonaryKey].scan(myMessage))

然后,这将导致 KeyNotFoundException 。我需要某种方式原子地锁定对象。

就像我说的,昨天我收到了一些建议,但是我不知道如何使用它们
  • 一个张贴者提到我应该首先尝试从字典中删除项目,因为这是ConcurrentDictionary的原子操作,然后重新添加它们。但是,我不确定如何向其他线程指示它应该等待项目被重新添加,而不是仅仅考虑它的缺失值并创建它。
  • 另一个张贴者提出了Threading.Interlocked.CompareExchange,我可以用它来标记该对象为“使用中”。但是我不知道如何处理正在使用的对象的情况-我将如何等待它?

  • 我有一些限制:我必须按顺序处理ConcurrentQueues,所以我不能放弃将对象放入Dictionary中的操作,或者稍后再回来-我需要阻止。该词典可能包含500,000项或更多,因此我确实需要ConcurrentDictionary的O(1)查找时间。

    有任何想法吗?抱歉,帖子很长

    谢谢,

    弗雷德里克

    最佳答案

    您可以将扫描线更改为:

    DictionaryItemType dictionaryItem;
    
    if (myConcurrentDictionary.TryGetValue(dictonaryKey, out dictionaryItem))
    {
        if (dictionaryItem.scan(myMessage))
    

    这样,您可以重新检查项目是否仍在字典中,如果不是,则不进入扫描分支。

    关于c# - 无法安全地锁定ConcurrentDictionary的值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4032212/

    10-11 01:31