在业务流程的某个地方,我的线程被锁定。所以在那之后,一切都将处于等待状态。如果它是这样的,那么我如何在不暂停应用程序的情况下继续进行。这意味着我不想终止应用程序。其实是面试题。
问问题
321 次
2 回答
1
首先,也是最重要的,强烈建议好好阅读一下死锁维基百科条目。特别是关于死锁处理的部分。
如果这是一个面试问题,面试官可能更感兴趣的是候选人对死锁如何发生以及如何防止和/或解决死锁的知识。
这是一个使用通过在一组对象上同步来创建 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 持有。两个线程都被另一个线程阻塞,因此所有线程都死锁了。
现在,可以重新编写此代码以使用显式锁来防止死锁(与通过“同步”关键字对资源对象实例进行隐式锁相反)。
请看下面的代码:
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 条件的“不抢占”条件的实例。实际上,等待的“tryLock”调用会在指定时间段后过期,从而防止应用程序无限期挂起。
于 2013-06-15T20:23:54.997 回答
0
使用jps
或任务管理器获取进程 ID,然后jstack -F <pid>
获取所有线程的堆栈跟踪和锁定信息(包括有关检测到的死锁的一些提示)。
于 2013-06-15T20:28:08.803 回答