Deadlock should be said to be a relatively common situation in concurrent programming, it can be said that if the program has a deadlock, it will have a fatal effect on the program; Therefore, it is very important to locate and repair deadlocks.

We all know that deadlocks occur when multiple objects or threads require locks held by each other but do not release the locks held by each other, causing both parties to permanently block.

Deadlock location and repair in Java

Pictured above, thread 1 holding an object 1 lock, thread 2 object 2 lock, this thread 1 and want to get 2 object lock, thread 2 for 1 object lock, at this time due to both of us didn’t get to want to lock, no task so didn’t also releases the lock, cause has been a stalemate, so blocking, and produce a deadlock;

Deadlock detection

Deadlock detection must be preceded by a deadlock. The following demo simulates a deadlock.

 

public class DeadlockDemo extends Thread {
private BaseObj first;
private BaseObj second;
public DeadlockDemo(String name, BaseObj first, BaseObj second) {
 super(name);
 this.first = first;
 this.second = second;
}
public void reentrantLock() throws InterruptedException {
 first.lock();
 System.out.println(String.format("%s 持有:%s 对象锁,等待获取:%s对象锁", this.getName(), first, second));
 second.lock();
 first.unlock();
 second.unlock();
}
@Override
public void run() {
 try {
 reentrantLock();
 } catch (Exception e) {
 e.printStackTrace();
 }
}
public static void main(String[] args) throws InterruptedException {
 ObjOne one = new ObjOne();
 ObjTwo two = new ObjTwo();
 DeadlockDemo thread1 = new DeadlockDemo("Thread1", one, two);
 DeadlockDemo thread2 = new DeadlockDemo("Thread2", two, one);
 thread1.start();
 thread2.start();
 thread1.join();
 thread2.join();
}
 }
Copy the code

Running the demo above will see that the application is blocked and cannot be finished; Only the following results are displayed:

Thread2 holds an objTwo object lock and is waiting to acquire an objOne object lock

Deadlock location and repair in Java

The demo didn’t finish because there was a deadlock, and the two threads were treating each other to acquire the object lock held by the other;

In order to solve the problem, we need to find out where the deadlock occurred. It is not easy to find the deadlock through the code, of course, our program is very easy to find, because we deliberately created the deadlock; So you need tools to detect deadlocks, the main tools available here are: JConsole, JVisualVM, JStack, etc., these tools are actually JDK built-in, usage is very similar;

Jvisualvm is used here to detect whether the current Demo program has a deadlock; Open The JVisualVM connection to the current application to see the application’s monitoring information, such as memory, CPU, performance, GC, and so on; Open the TAB entry thread to view the program thread information, here it is obvious to see the prompt that the program is detected in addition to deadlock!

Deadlock location and repair in Java

Click thread Dump to see the stack information for the thread, which shows details about the thread and locates deadlocks.

Deadlock location and repair in Java

Thread1 is waiting for Thread1, and Thread1 is waiting for Thread1. The following stack information can be used to locate the location of deadlock.

Deadlock location and repair in Java

Deadlock scanning

In addition to scanning for deadlocks after finding problems in the program, we can also scan the program in real time to find whether there are deadlocks in the program;

The JDK provides the MXBean Api for scanning your program for deadlocks, and ThreadMXBean provides the findDeadlockedThreads() method for finding the thread causing the deadlock. Here in the above demo program to add a method for scanning deadlocks, although this method can scan deadlocks, but because every time the thread snapshot will have a relatively large impact on the program performance, so use with caution;

 

public static void scanDeadLock() { ThreadMXBean mxBean = ManagementFactory.getThreadMXBean(); Runnable runnable = () -> { long[] ids = mxBean.findDeadlockedThreads(); System.out.println(" Scan deadlock...") ); if (ids ! = null) { ThreadInfo[] threadInfos = mxBean.getThreadInfo(ids); for (ThreadInfo threadInfo : threadInfos) { System.out.println(threadInfo); }}}; ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(5, Executors.defaultThreadFactory()); executorService.scheduleAtFixedRate(runnable, 1, 5, TimeUnit.SECONDS); }Copy the code

Deadlock location and repair in Java

Avoid deadlock

The best way to avoid deadlocks is to avoid deadlocks. For example, in the demo above, we can use the tryLock method instead of using the lock() method with no arguments. TryLock can also specify a timeout period before the lock is obtained.

1. Avoid using multiple locks and holding locks for a long time;

2. Design the acquisition sequence of several locks

3. Use the lock acquisition method with timeout

 

Deadlock location and repair in Java