当一个线程永远地持有一个锁,并且其他线程都尝试去获得这个锁时,那么它们将永远被阻塞,这个我们都知道。如果线程A持有锁L并且想获得锁M,线程B持有锁M并且想获得锁L,那么这两个线程将永远等待下去,这种情况就是最简单的死锁形式。
在数据库系统的设计中考虑了监测死锁以及从死锁中恢复,数据库如果监测到了一组事务发生了死锁时,将选择一个牺牲者并放弃这个事务。Java虚拟机解决死锁问题方面并没有数据库这么强大,当一组Java线程发生死锁时,这两个线程就永远不能再使用了,并且由于两个线程分别持有了两个锁,那么这两段同步代码/代码块也无法再运行了—-除非终止并重启应用。
死锁是设计的BUG,问题比较隐晦。不过死锁造成的影响很少会立即显现出来,一个类可能发生死锁,并不意味着每次都会发生死锁,这只是表示有可能。当死锁出现时,往往是在最糟糕的情况—-高负载的情况下。
死锁的例子 :
class DeadThread implements Runnable
{
private Boolean flag;
public DeadThread(boolean flag)
{
this.flag = flag;
}
@Override
public void run()
{
if(flag)
{
synchronized (lockObject.locka)
{
System.out.println("if locka");
synchronized (lockObject.lockb)
{
System.out.println("if locka");
}
}
}
else
{
synchronized (lockObject.lockb)
{
System.out.println("else lockb");
synchronized (lockObject.locka)
{
System.out.println("else locka");
}
}
}
}
}
//提供所的类文件
class lockObject
{
static Object locka = new Object();
static Object lockb = new Object();
}
//main 函数
public static void main(String[] args)
{
Thread t1 = new Thread(new DeadThread(true));
Thread t2 = new Thread(new DeadThread(false));
t1.start();
t2.start();
}
输出结果 :