Can I use dictionary elements as lock objects?

I have several queues accessed by several threads. To ensure thread safety, I did the following:

private static Dictionary<string, Queue<string>> MyQueues = new Dictionary<string, Queue<string>>(); public static string GetNextQueueElementForKey(string key) { string res = string.Empty; if (MyQueues.Keys.Contains(key)) { Queue<string> queue = MyQueues[key]; lock (queue) { if (queue.Count() > 0) { res = queue.Dequeue(); } } } return res; } 

I could also block MyQueues , but then I would block more than necessary. Therefore, my question is that if locking the object contained in the dictionary works, assuming that the key value (queue) never changes.

+6
source share
3 answers

You can - but I didn't do it at all. Personally, I usually try to block regular instances of System.Object that are not used for anything else, and ideally are not even exposed to any code other than locking classes on them. Thus, you can be absolutely sure that nothing else will be blocked.

In this case, it looks like you have control over the queues, so you know that they will not be used by other code, but it is possible that the code inside Queue<T> will be blocked on this . This is probably not the case, but this is what I would worry about.

Basically, I'm sorry that .NET did not use the Java approach for a “monitor for every object” —I would like Monitor be an instance of the class.

(I assume that you are only actually reading a dictionary from multiple threads? It is unsafe to use dictionaries for multithreaded read / write.)

+6
source

The fact that it is an element in the dictionary is largely irrelevant - as long as it is a reference type (which is Queue<string> ) - then each queue, when it is retrieved from the dictionary, will be the same object instance every time . This means that it will work quite reasonably with blocking at the queue level.

So, in principle: yes, this should work fine - while Enqueue does the same blocking in the queue. As John points out, whether this should be done is another question.

Personally, I am still of the opinion that Monitor should have been a non-static type and that you could only block Monitor instances, not any object .

+2
source

So my question is if locking the object contained in the dictionary will work - assuming that the key value (queue) never changes.

Take a look at your code here:

 lock (queue) { if (queue.Count() > 0) { res = queue.Dequeue(); } } 

You can, but I wouldn’t. You should never block the object itself , since you can compete with other code streams that will block on the same object, including Queue<T> (which could block this ).

So, at a minimum, you should create a dedicated lock object for each queue.

But is there a reason you are not using ConcurrentQueue<T> ? That would be the easiest solution, and he would shift the burden of getting the right to the Frame.

+1
source

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


All Articles