我编写了下面的Java代码来创建死锁,我将资源String变量传递给线程,并使用 synchronized 块将其锁定,并在其中建立了无限循环,这样第一个线程就永远不会永远离开它,所以第二个线程将永远无法访问它。
set serveroutput on
set linesize 2000 --> this
spool ..
然后在另一个窗口中,我编写了如下代码来检测死锁,
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);
}
}
}
}
}
但是看门狗什么也没发现。
答案 0 :(得分:4)
您的代码中没有死锁。当两个(或更多)线程互相等待时,就会发生死锁。这里不是这种情况。一个线程正在等待,另一个线程处于活动状态(处于无限循环中,但这并不意味着它处于死锁状态。)
答案 1 :(得分:1)
获得死锁的一种方法是乱序同步。本示例使两个线程死锁,然后使用上面的检查器找到它们。都可以从主要方法运行。
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,但是有时线程只会死锁。有时,一个线程会在另一个线程开始之前完成。