Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to find Java deadlock by programming

2025-01-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

Today, I will talk to you about how to find Java deadlocks by programming. Many people may not know much about it. In order to make you understand better, the editor has summarized the following contents for you. I hope you can get something according to this article.

Deadlock means that two or more actions have been waiting for other actions to be completed, so that all actions are always in a blocking state. It is very difficult to detect a deadlock during the development phase, and it is often necessary to restart the program to release the deadlock. To make matters worse, deadlocks usually occur in the heaviest production process, and it is not easy to find it in testing. This is said because all possible crossover between test threads is unrealistic. Although there are some static analysis libraries that can help us find possible deadlocks, it is necessary to detect deadlocks at run time and get useful information so that we can solve this problem or restart the program. Or do something else.

Use the ThreadMXBean class to detect deadlocks in programming

Java 5 introduces the ThreadMXBean interface, which provides a variety of ways to monitor threads. I recommend that you understand all of these methods, because when you are not using external tools, they provide you with a lot of useful operations for you to monitor program performance. Here, the method we are interested in is findMonitorDeadlockedThreads, if you are using Java 6, the corresponding method is findDeadlockedThreads. The difference between the two is that findDeadlockedThreads can also detect deadlocks caused by owner locks (java.util.concurrent), while findMonitorDeadlockedThreads can only detect monitor locks (for example, synchronous blocks). Since keeping the old version of the method is only for compatibility reasons, I will use the new version of the method. Here, the idea of programming is to encapsulate the periodic detection of deadlocks into a reusable component, and then we just need to start it and let it go.

One way to achieve scheduling is through the executor framework, a set of well-abstract and easy-to-use multithreaded classes.

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool (1); this.scheduler.scheduleAtFixedRate (deadlockCheck, period, period, unit)

It's that simple. After we set a specific time by selecting a period and time unit, we get a thread that is called periodically. Next, we want to extend the function to allow the user to provide the behavior triggered when the program detects a deadlock. *, we need a method to receive a series of objects that describe all threads in the deadlock.

Void handleDeadlock (final ThreadInfo deadlockedThreads)

Now, everything is ready to implement the deadlock detection class.

Public interface DeadlockHandler {void handleDeadlock (final ThreadInfo deadlockedThreads);} public class DeadlockDetector {private final DeadlockHandler deadlockHandler; private final long period; private final TimeUnit unit; private final ThreadMXBean mbean = ManagementFactory.getThreadMXBean; private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool (1); final Runnable deadlockCheck = new Runnable {@ Override public void run {long deadlockedThreadIds = DeadlockDetector.this.mbean.findDeadlockedThreads; if (deadlockedThreadIds! = null) {ThreadInfo threadInfos = DeadlockDetector.this.mbean.getThreadInfo (deadlockedThreadIds); DeadlockDetector.this.deadlockHandler.handleDeadlock (threadInfos);} Public DeadlockDetector (final DeadlockHandler deadlockHandler, final long period, final TimeUnit unit) {this.deadlockHandler = deadlockHandler; this.period = period; this.unit = unit;} public void start {this.scheduler.scheduleAtFixedRate (this.deadlockCheck, this.period, this.period, this.unit);}}

Let's try it. First, we will create a handler to output information about deadlock threads to System.err. In real situations, we can use it to send emails, such as:

Public class DeadlockConsoleHandler implements DeadlockHandler {@ Override public void handleDeadlock (final ThreadInfo deadlockedThreads) {if (deadlockedThreads! = null) {System.err.println ("Deadlock detected!"); Map stackTraceMap = Thread.getAllStackTraces; for (ThreadInfo threadInfo: deadlockedThreads) {if (threadInfo! = null) {for (Thread thread: Thread.getAllStackTraces.keySet) {if (thread.getId = = threadInfo.getThreadId) {System.err.println (threadInfo.toString.trim); for (StackTraceElement ste: thread.getStackTrace) {System.err.println ("t" + ste.toString.trim) }}

This process is repeated in all stack traces and the corresponding stack trace is printed for each thread information. In this way, we can know exactly where and what each thread is waiting for. But this approach has a drawback-when a thread waits temporarily, it may be treated as a temporary deadlock, causing a false alarm. For this reason, when we deal with deadlocks, the original thread cannot continue to exist and the findDeadlockedThreads method returns that there is no such thread. In order to avoid possible NullPointerException, we need to be aware of this situation. * let's promote a deadlock to see how the system works.

DeadlockDetector deadlockDetector = new DeadlockDetector (new DeadlockConsoleHandler, 5, TimeUnit.SECONDS); deadlockDetector.start; final Object lock1 = new Object; final Object lock2 = new Object; Thread thread1 = new Thread (new Runnable {@ Override public void run {synchronized (lock1) {System.out.println ("Thread1 acquired lock1"); try {TimeUnit.MILLISECONDS.sleep;} catch (InterruptedException ignore) {} synchronized (lock2) {System.out.println ("Thread1 acquired lock2");}); thread1.start Thread thread2 = new Thread (new Runnable {@ Override public void run {synchronized (lock2) {System.out.println ("Thread2 acquired lock2"); synchronized (lock1) {System.out.println ("Thread2 acquired lock1");}); thread2.start

Output:

Thread1 acquired lock1 Thread2 acquired lock2 Deadlock detected! "Thread-1" Id=11 BLOCKED on java.lang.Object@68ab95e6 owned by "Thread-0" Id=10 deadlock.DeadlockTester$2.run (DeadlockTester.java:42) java.lang.Thread.run (Thread.java:662) "Thread-0" Id=10 BLOCKED on java.lang.Object@58fe64b9 owned by "Thread-1" Id=11 deadlock.DeadlockTester$1.run (DeadlockTester.java:28) java.lang.Thread.run (Thread.java:662)

Remember, deadlock detection can be expensive, and you need to use your program to test whether you really need deadlock detection and how often. I recommend a deadlock detection interval of at least a few minutes, because more frequent detection doesn't make much sense, because we don't have a recovery plan, all we can do is debug and handle errors or restart the program and pray that deadlocks don't happen again. If you have good suggestions on solving the deadlock problem or have questions about this solution, please leave a message below.

After reading the above, do you have any further understanding of how to programmatically discover Java deadlocks? If you want to know more knowledge or related content, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report