Lock performance in two different scenarios

I have a class with 2 built-in lists containing over 1000 elements, such as

public class A { private List<long> aList = new List<long>(); private List<long> bList = new List<long>(); void MethodThatUsesAList() { //Works with aList } void MethodThatUsesBList() { //Works with bList } void MethodThatUsesBoth() { //Works with both lists } } 

Now I want the thread of this class to be safe, and there are two different scenarios that I see with locks, first creating

 object _synchObject = new object() 

and lock this object in all methods, or the second to lock each list when it is used, My first question is: which method is preferable? and in the case of the second, it is preferable whether the performance problem is to use a lock like this?

  void MethodThatUsesBoth() { lock(aList){ lock(bList){ //Works with both lists } } } 
+4
source share
3 answers

There are two separate questions here:

  • Use one combination lock or two separate locks
  • Whether to use separate objects for blocking or the lists themselves (or their SyncRoot s)

To some extent, they are separable - if you use two separate locks, you can create two separate objects for locking, one for each list.

If you want MethodThatUsesAList and MethodThatUsesBList to work simultaneously, you will need two separate locks. Then you will need to make sure that at any time when you can purchase both locks, you purchase them in the same order. This means talking about the entire codec in any method that receives a lock: you need to make sure that it does not call another method, which, for example, acquires a different lock.

If your specific scenario is unlikely to suffer from all methods that are effectively blocked for other threads by any thread executing any of them, I would use only one lock for simplicity.

In any case, I would personally go for "private" locks, which no other code knows about. It's easier for me to talk about code written this way. Using the list itself or the synchronization root may very well be absolutely accurate - but I just prefer to think of locks that can't get anything.

+3
source
 void MethodThatUsesBoth() { lock(((ICollection)aList).SyncRoot){ lock(((ICollection)bList).SyncRoot){ //Works with both lists } } } void MethodThatUsesAList() { lock(((ICollection)aList).SyncRoot){ } } void MethodThatUsesBList() { lock(((ICollection)bList).SyncRoot){ } } 

In your other solution, I think this is not good, because you block access to bList when you work only with aList. This is not a good solution for performance.

+1
source

In general, I prefer the former (another unused mutex). There is no real value for this, and it is too easy to get the latter wrong, it is too easy to create deadlocks.

0
source

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


All Articles