Dead ends and synchronous methods

I found one of the code in Stack Overflow, and I thought it was very similar to what I came across, but I still don't understand why this is getting into a dead end. An example was taken from detecting Deadlock in Java :

Class A { synchronized void methodA(B b) { b.last(); } synchronized void last() { System.out.println(" Inside A.last()"); } } Class B { synchronized void methodB(A a) { a.last(); } synchronized void last() { System.out.println(" Inside B.last()"); } } Class Deadlock implements Runnable { A a = new A(); B b = new B(); // Constructor Deadlock() { Thread t = new Thread(this); t.start(); a.methodA(b); } public void run() { b.methodB(a); } public static void main(String args[] ) { new Deadlock(); } } 

In this case, when the Deadlock () constructor is called, it starts as a thread. When he does this, the run () method is called. It is called b.methodB (a), which then calls a.last () to just print the expression. At the same time, a.methodA (b) will call b.last (). There are no cross-dependencies on any object, and they also do not execute the method at the same time. Even if they are, a synchronized keyword will be queued, right? But how did it come to a standstill from time to time? This is not all the time, but sometimes it comes to a standstill, which is completely unpredictable. What makes this come to a standstill and workarounds?

+5
source share
3 answers

It is possible that the execution of these two statements is intertwined:

 Thread 1: a.methodA(b); //inside the constructor Thread 2: b.methodB(a); //inside run() 

to execute a.methodA() , Thread 1 will have to obtain a lock on object A

to execute b.methodB() , Thread 2 will have to obtain a lock on object B

For Thread 1 methodA() to then call the synchronous method on instance B , it will need to get a lock on B held by Thread 2, which will call Thread 1 until the lock is released.

For Thread2 methodB() , to be able to call the synchronized method on instance A , it will need to get the lock held on A thread 1, which will cause Thread 2 to wait.

Since each thread holds the lock that the other thread wants, a deadlock occurs when no thread can get the required lock and no thread releases the locks that it holds.

It is important to understand that this code will not create a deadlock in 100% of cases when you run it - only when the four key steps (Thread1 holds the lock and tries to get B, which Thread 2 has lock B and tries to get A) are executed in a certain order. Run this code enough times, and this order will happen.

+18
source

synchronized puts a lock on an object that must be obtained before methods or code blocks can be executed. Since it blocks entire objects, it is an inelegant tool that sometimes looks pretty easy to use, but gives locks like this where no actual disputed data is read or written.

a.method(b) blocks object a . b.method(a) blocks the object b . And none of the threads can continue to call b.last() or a.last() , because they both wait for the other object to release its lock.

+2
source

Call method A makes (efficiently) lock (a), lock (b). If the task then switches and tries Method B, it immediately blocks (b).

0
source

All Articles