尝试检测自己创建的死锁



我写了下面的Java代码来创建死锁,我向线程传递了一个资源String变量,并使用synchronized块将其锁定,并在其中设置了一个无限循环,这样第一个线程就永远不会离开它,所以第二个线程就不能永远访问它。

public class MainClass {
public static void main(String[] args) {
String resourcs = "testResource";
MainClass M = new MainClass();
Thread firstThread = new Thread(M.new MyThread("First",resourcs));
Thread seconThread =  new Thread(M.new MyThread("Second",resourcs));
firstThread.start();
seconThread.start();
}
class MyThread implements Runnable{
String resource;
String name;
public MyThread(String name,String resource) {
this.resource = resource;
this.name = name;
}
@Override
public void run() {
synchronized (resource) {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Still working on the thread :"+name);
}
}
}
}
}

然后在另一个窗口中,我写了如下检测死锁的代码,

import java.lang.management.ManagementFactory; 
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
public class DetectDeadLock {
public static void main(String args[]) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long[] threadIds = bean.findDeadlockedThreads();
if (threadIds != null) {
ThreadInfo[] infos = bean.getThreadInfo(threadIds);
for (ThreadInfo info : infos) {
StackTraceElement[] stack = info.getStackTrace();
System.out.println("here");
// Log or store stack trace information.
}
}
}
}

但是看门狗什么也没发现。


  1. 我是否正确创建了死锁(我认为是的,因为控制台只打印第一个线程的代码(
  2. 我是否必须等待一段时间(idk多少(,等待"看门狗"代码检测死锁

您的代码中没有死锁。当两个(或多个(线程相互等待时,就会发生死锁。这里的情况并非如此。一个线程在等待,另一个线程处于活动状态(处于无休止的循环中,但这并不意味着它处于死锁状态。(

获得死锁的一种方法是无序同步。本例使两个线程死锁,然后使用上面的检查器查找它们。这一切都可以从一个主方法中运行。

final Object a = new Object();
final Object b = new Object();
CountDownLatch latch = new CountDownLatch(2);

new Thread(()->{
System.out.println(Thread.currentThread().getId() + " running");
synchronized(a){    
try{
latch.countDown();
latch.await();
} catch(InterruptedException e){
return;
}
synchronized(b){
System.out.println("no deadlock");  
}
}   

}).start();

new Thread(()->{
System.out.println(Thread.currentThread().getId() + " running");
synchronized(b){
try{
latch.countDown();
latch.await();
} catch(InterruptedException e){
return;
}
synchronized(a){
System.out.println("no deadlock");  
}
}   

}).start();

通过添加一个小延迟,我可以找到两个死锁的线程id。

Thread.sleep(100);
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long[] threadIds = bean.findDeadlockedThreads();
for(long id: threadIds){
System.out.println(id + " deadlocked");
}

然后输出看起来像:

18运行

19运行

19死锁

18死锁

Thread.sleep可以省略,但存在竞争条件。bean.findDeadlockedThreads();可能在出现死锁之前发生。即使有睡眠,也会有种族状况,但这种情况非常罕见。闩锁可以保证。

CountDownLatch可以被删除,但线程有时只会死锁。有时,一个线程会在另一个线程开始之前完成。

最新更新