Avoiding nested synchronization and resulting deadlock

I need to lock two objects in functionality, and the current code is as follows:

Object obj1 = ...//get from somewhere Object obj2 = ...//get from somewhere synchronized(obj1){ ...//blah synchronized(obj2){ ...//blah } } 

As you can see, this is a simple and direct recipe for deadlocks if another thread runs this piece of code with obj1 and two inverse.
Is there a way to avoid this situation with concurrency -utils locks?

I was thinking about saving a map of objects and their locks and checking to see if they were available, but it might not seem like they came up with a clean way that would predict the blocking order.

+2
java concurrency
Mar 01 2018-11-11T00:
source share
4 answers

Although you keep the lock order if obj1 is enabled with obj2, you will run into a dead end.

You must look for another solution to avoid these cases: order blocking + additional blocking lock

 int fromHash = System.identityHashCode(obj1); int toHash = System.identityHashCode(obj2); if (fromHash < toHash) { synchronized (obj1) { synchronized (obj2) { ........ } } } else if (fromHash > toHash) { synchronized (obj2) { synchronized (obj1) { ........ } } } else { synchronized (TIE_LOCK) { synchronized (fromAcct) { synchronized (toAcct) { ... } } } 
+6
Mar 01 2018-11-11T00:
source share

Depending on what you are doing, you can take what you want from the first locked object and use this information to process the second locked object. eg.

instead

 synchronized(list1) { for(String s : list1) { synchronized(list2) { // do something with both lists. } } } 

do it

 List<String> listCopy; synchronized(list1) { listCopy = new ArrayList<String>(list1); } synchornized(list2) { // do something with liastCopy and list2 } 

You can see that you only have a lock at a time, so you won’t get a dead end.

+3
Mar 01 '11 at 9:01
source share

You need to sequentially fix the order of obj1, and then obj2. If you never violate this order, you will not have deadlocks.

+2
Mar 01 2018-11-11T00:
source share

Essentially, you have the problem of dining philosophy.

https://en.wikipedia.org/wiki/Dining_philosophers_problem

Ovidiu Lupas answer is similar to Dijkstra Resource Heirarchy solution, but there are 3 more solutions explained on the wiki page

This is what the arbiter's decision looks like. If all the objects that you use are inherited from the same type, you can use static class variables to implement arbiters in the object class.

 import java.util.concurrent.locks.Lock; public void init() { Lock arbitrator = new Lock(); } public void meth1() { arbitrator.lock(); synchronized (obj1) { synchronized (obj2) { arbitrator.unlock(); // Do Stuff } } } public void meth2() { arbitrator.lock(); synchronized (obj2) { synchronized (obj1) { arbitrator.unlock(); // Do Stuff } } } 

The Chandy / Misra solution requires a lot of posts, so I'm not going to implement it, but wikipedia has a pretty good explanation.

+1
Jan 15 '15 at 20:18
source share



All Articles