Introduction If we encounter thread deadlock in the program, how to solve it?

This article will take a step-by-step approach to Java problem solving, starting with a practical example. Deadlock code has written Java multithreaded programs should know that a very important thing in multithreading is the synchronization of the state, but in the process of state synchronization, a careless may lead to deadlock problems.

One of the simplest deadlock situations is when thread1 occupies resource 1 and then tries to acquire resource 2. Thread2 takes resource 2 and wants to take resource 1.

For a concrete example: public class TestDeadLock {public static Object lock1= new Object(); public static Object lock2= new Object(); public static void main(String[] args) { Runnable runnable1= ()-> { System.out.println(“in lock1”); synchronized(lock1){ System.out.println(“Lock1 lock obj1”); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized(lock2){ System.out.println(“Lock1 lock obj2”); }}};

Runnable runnable2= ()-> { System.out.println("in lock2"); synchronized(lock2){ System.out.println("Lock2 lock obj2"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized(lock1){ System.out.println("Lock2 lock obj1"); }}}; Thread a = new Thread(runnable1); Thread b = new Thread(runnable2); a.start(); b.start(); }}Copy the code

We run the code above:

In lock1Lock1 lock obj1 in lock2Lock2 lock obj2 In lock2Lock2 lock obj2 It is easy to analyze the cause of a deadlock when the code is simple, but not so easy when the code is on a very large online project.

So how do we do that?

One way to do this is to use the control+break command.

Control+Break stands for Control+ Backslash on Linux and the Control+Break button on Windows.

Of course, there is a more general use of:

Kill -quit pid command.

We use the JPS command to get the process ID of the Java program, and then execute the kill -quit command. After execution, we find that the running Java process outputs some extra logs, and these extra logs are the key to finding deadlocks.

Note that the kill command does not terminate the program.

The output content is more, we explain part by part.

Full thread dump

The first part of the log is the Full Thread dump, which contains state information for all threads in the JVM.

Let’s look at two key threads in our code: Elapsed =230.16s TID =0x00007fc926061800 nID =0x6403 Waiting for monitor entry [0x0000700008d6a000] java.lang.Thread.State: BLOCKED (on object monitor) at com.flydean.TestDeadLock.lambda mainmainmain0(TestDeadLock.java:21) – waiting to lock <0x0000000787e868f0> (a java.lang.Object) – locked <0x0000000787e868e0> (a java.lang.Object) at com.flydean.TestDeadLock$$Lambda$14/0x0000000800b69840.run(Unknown Source) at Java. Lang. Thread. The run ([email protected] / Thread. Java: 832)

Elapsed =230.16s TID =0x00007fc924869800 NID =0x6603 Waiting for monitor entry [0x0000700008e6d000] java.lang.Thread.State: BLOCKED (on object monitor) at com.flydean.TestDeadLock.lambda mainmainmain1(TestDeadLock.java:36) – waiting to lock <0x0000000787e868e0> (a java.lang.Object) – locked <0x0000000787e868f0> (a java.lang.Object) at com.flydean.TestDeadLock$$Lambda$15/0x0000000800b69c40.run(Unknown Source) at Java.lang.thread. run([email protected]/ thread.java :832) lists the Thread name, priority of the Thread, CPU time, whether it is a daemon Thread, Thread ID, Thread status and other useful information. Looking at the output above, we see that both threads are BLOCKED, waiting for the Object Monitor. Remember a few states of threads? Let’s review it again.

Deadlock detection The next part of deadlock detection is the one we care about most. Found one Java-level deadlock:

“Thread-0”: waiting to lock monitor 0x00007fc926807e00 (object 0x0000000787e868f0, a java.lang.Object), which is held by “Thread-1″”Thread-1”: waiting to lock monitor 0x00007fc926807f00 (object 0x0000000787e868e0, a java.lang.Object), which is held by “Thread-0”

Java stack information for the threads listed above:

“Thread-0”: at com.flydean.TestDeadLock.lambda mainmainmain0(TestDeadLock.java:21) – waiting to lock <0x0000000787e868f0> (a java.lang.Object) – locked <0x0000000787e868e0> (a java.lang.Object) at com.flydean.TestDeadLock$$Lambda$14/0x0000000800b69840.run(Unknown Source) at Java. Lang. Thread. The run ([email protected] / Thread. Java: 832)

“Thread-1”: at com.flydean.TestDeadLock.lambda mainmainmain1(TestDeadLock.java:36) – waiting to lock <0x0000000787e868e0> (a java.lang.Object) – locked <0x0000000787e868f0> (a java.lang.Object) at com.flydean.TestDeadLock$$Lambda$15/0x0000000800b69c40.run(Unknown Source) at Java. Lang. Thread. The run ([email protected] / Thread. Java: 832)

It is clear that two separate threads have obtained the lock that the other needs, resulting in a deadlock.

At the same time, the information of Thread Stack is listed in detail for our analysis.

If we add the argument -xx :+PrintConcurrentLocks, we also print the concurrent lock information obtained by each thread.

Heap information

The final section is Heap statistics: Heap garbage-first heap total 133120K, used 3888K [0x0000000780000000, 0x0000000800000000) region size 1024K, 4 young (4096K), 0 survivors (0K) Metaspace used 1122K, capacity 4569K, committed 4864K, reserved 1056768K class space used 108K, capacity 412K, committed 512K, reserved 1048576K

If we add the -xx :+PrintClassHistogram command, we can also output additional class histogram statistics.

Use the Control+Break command to analyze Java deadlock problems.