在业务流程的某个地方,我的线程被锁定了。所以在那之后一切都将处于等待状态。如果它是这样的,那么我如何继续而不暂停应用程序。 这意味着我不想终止该应用程序。实际上是一个面试问题。
答案 0 :(得分:1)
首先,强烈建议您仔细阅读deadlocks维基百科条目。特别是关于deadlock handling的部分。
如果这是一个面试问题,那么面试官可能对候选人对死锁如何发生以及如何预防和/或解决死因的了解更感兴趣。
这是使用同步对象集创建java死锁的基本示例
private static void synchronizedBlockDeadlock()
{
final Object resource1 = new Object();
final Object resource2 = new Object();
Runnable thread1 = new Runnable()
{
public void run()
{
synchronized (resource1)
{
final int sleepTimeMs = 1000;
try
{
Thread.sleep(sleepTimeMs);
}
catch (InterruptedException e) {}
synchronized (resource2)
{
System.out.println("In thread1");
}
}
}
};
Runnable thread2 = new Runnable()
{
public void run()
{
synchronized (resource2)
{
final int sleepTimeMs = 1000;
try
{
Thread.sleep(sleepTimeMs);
}
catch (InterruptedException e) {}
synchronized (resource1)
{
System.out.println("In thread2");
}
}
}
};
new Thread(thread1).start();
new Thread(thread2).start();
}
首先,两个线程(有效地)同时运行。线程1将获取对资源1的锁定并暂时休眠,使得线程2将获得对资源2的锁定。这当然是基于假设线程2能够在线程1中的睡眠调用返回之前启动。现在,线程2尝试获取由线程1保持的资源1上的锁,因此它无限期地阻塞。线程1唤醒并尝试获取资源2上的锁,该资源由线程2保持。两个线程都被阻塞,因此所有线程都被死锁。
现在,可以重新编写此代码以使用显式锁来防止死锁(而不是通过'synchronized'关键字对资源对象实例进行隐式锁定。)
请参阅以下代码:
private static void explicitLockDeadlock()
{
final Lock lock1 = new ReentrantLock();
final Lock lock2 = new ReentrantLock();
Runnable thread1 = new Runnable()
{
public void run()
{
try
{
lock1.tryLock(5, TimeUnit.SECONDS);
System.out.println("Thread-1: Lock 1 acquired");
final int sleepTimeMs = 1000;
Thread.sleep(sleepTimeMs);
lock2.tryLock(5, TimeUnit.SECONDS);
System.out.println("Thread-1: Lock 2 acquired");
}
catch (InterruptedException e) {}
finally
{
lock1.unlock();
}
System.out.println("In thread1");
}
};
Runnable thread2 = new Runnable()
{
public void run()
{
try
{
lock2.tryLock(5, TimeUnit.SECONDS);
System.out.println("Thread-2: Lock 2 acquired");
lock1.tryLock(5, TimeUnit.SECONDS);
System.out.println("Thread-2: Lock 1 acquired");
}
catch (InterruptedException e) {}
finally
{
lock2.unlock();
}
System.out.println("In thread2");
}
};
new Thread(thread1).start();
new Thread(thread2).start();
}
这种方法是抢占线程的一个实例,该线程可能会死锁,或者破坏4 Coffman conditions的“无抢占”条件。实际上,等待的'tryLock'调用在指定的时间段后过期,从而阻止应用程序无限期挂起。
答案 1 :(得分:0)
使用jps
或任务管理器获取进程ID,然后使用jstack -F <pid>
获取所有线程的堆栈跟踪和锁定信息(包括有关检测到的死锁的一些提示)。