Threading Question

Recently I had an interview question in a test that was similar to the one below, I don't have much experience with thread development, can someone please advise me on how to approach this question ?:

public class StringQueue { private object _lockObject = new object(); private List<string> _items = new List<string>(); public bool IsEmpty() { lock (_lockObject) return _items.Count == 0; } public void Enqueue(string item) { lock (_lockObject) _items.Add(item); } public string Dequeue() { lock (_lockObject) { string result = _items[0]; _items.RemoveAt(0); return result; } } } 

Is the following method a thread safe with the above implementation and why?

 public string DequeueOrNull() { if (IsEmpty()) return null; return Dequeue(); } 
+8
multithreading c #
source share
3 answers

It seems to me that the answer is no.

While the isEmpty () procedure locks the object, it is released as soon as the call returns - another thread can potentially call DequeueOrNull () between the call to IsEmpty () and Dequeue () (after which the object is unlocked), thereby removing the only element that existed, making Dequeue () invalid at this time.

A plausible solution would be to put the lock on both operators in DequeueOrNull (), so that no other thread could call DeQueue () after checking, but before DeQueue ().

+9
source share

It is not thread safe. In the marked line, it is possible that the Dequeue method is called from another thread and, therefore, the subsequent Dequeue returns an incorrect value:

 public string DequeueOrNull() { if (IsEmpty()) return null; /// << it is possible that the Dequeue is called from another thread here. return Dequeue(); } 

Stream Security Code:

 public string DequeueOrNull() { lock(_lockObject) { if (IsEmpty()) return null; return Dequeue(); } } 
+3
source share

No, because the state of _items can potentially change between thread-safe IsEmpty() and thread-safe calls to Dequeue() .

Correct it as follows: _items locked during the whole operation:

 public string DequeueOrNull() { lock (_lockObject) { if (IsEmpty()) return null; return Dequeue(); } } 

Note: depending on the _lock implementation _lock you can avoid double locking the resource by moving the guts of IsEmpty() and Dequeue into separate helper functions.

+2
source share

All Articles