Unable to safely lock ConcurrentDictionary value

I'm having trouble locking an item in a collection - in particular, ConcurrentDictionary.

I need to accept a message, look at this message in the dictionary, and then run a long scan. Since the program takes up a lot of memory, after scanning, objects return true if they believe that this is a good time to delete it (which I do by deleting it from the Dictionary). However, another thread may arrive at the same time and try to access the same object immediately after deletion. This is my first attempt:

string dictionaryKey = myMessage.someValue;

DictionaryObject currentObject = myConcurrentDictionary.GetOrAdd(dictionaryKey, new DictionaryObject());
// we can be interrupted here
lock (currentObject)
{
    //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 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");
    }
}

- , , . , , Monitor.Enter Monitor.Exit, :

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 still 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 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");
    }
}

KeyNotFoundException .

- , , , , ? - concurrency !

,

+2
4

, . , , scan(). .

, , lock Monitor.

string dictionaryKey = myMessage.someValue;

DictionaryObject currentObject = null;
if (myConcurrentDictionary.TryRemove(dictionaryKey, out currentObject))
{
    //KeyNotFoundException is possible on line below
    if (!currentObject.scan(myMessage)) // Scans the message - returns true if the object says its OK to remove it from the dictionary
    {
      if (!myConcurrentDictionary.TryAdd(dictionaryKey, currentObject))
       throw new Exception("Was unable to re-insert a DictionaryObject that is not OK for deletion");
    }
} 

, , , - scan(). TryAdd. , .

, , , "" , atomically: 1. 2. " ".

  • , ,
  • , scan() .
+3

, "" .

(Monitor.Enter), . , . , - , .

, . , , - - , . , , , ...

0

...

, concurrentDictionary , .

, , .

, .

, , , , .

, .

0

How about including a field in an object that indicates which thread belongs to it, and using Threading.Interlocked.CompareExchange to try to acquire it? Figure that if the object is used, the code should not be blocked, but simply refuse the operation.

0
source

Source: https://habr.com/ru/post/1771681/


All Articles