Lock two objects without deadlock

I have a question that is easily solvable in C ++, but in C # I still cannot find a good solution:

I have a function foo that should block two objects, and this function can be called with arguments in reverse order, for example:

static void foo(object o1, object o2) { lock (o1) { lock (o2) { ... } } } static void bar(object a, object b) { ThreadPool.QueueUserWorkItem(s => foo(a, b)); ThreadPool.QueueUserWorkItem(s => foo(b, a)); } 

This is a book way to make a standstill. The standard way to fix this is to always lock objects in the same order. In C ++, I could compare pointers, but in "safe" C # I don't know anyone but a very ugly solution to Monitor.TryEntry (see below). Is there anything better? Note that objects are mutable, and I cannot rely on Equals , GetHashCode , IComparable .

  static void foo(object o1, object o2) { const int Timeout = 1000; while (true) { if (Monitor.TryEnter(o1, Timeout)) { try { if (Monitor.TryEnter(o2, Timeout)) { try { ... return; } finally { Monitor.Exit(o2); } } } finally { Monitor.Exit(o1); } } } } 
+4
source share
2 answers

If you want to use the same approach with ordered locking, you can add some property to the object that you use to lock and compare based on this. You can use classes or interfaces depending on what works in your case (i.e., implement IComparable for lock objects). The example below uses a class with a Less comparison function:

 class ComparableLockingObject { static int LastOrderValue = 0; private orderValue = LastOrderValue++; public bool Less(ComparableLockingObject other) { return this.orderValue < other.orderValue; } } static void foo(ComparableLockingObject o1, ComparableLockingObject o2, Action action) { if (o2.Less(o1)) { var temp = o1; o1 = o2; o2 = temp; } lock (o1) { lock (o2) { action(); } } } 
+3
source

You do not need to block these objects. You block code that executes logic:

  static object lockObject = new object(); static void foo(object o1, object o2) { lock (lockObject) { // this code will be executed on one thread at the time. Why lock o1 & o2?? } } 
+2
source

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


All Articles