维基百科的定义:
死锁(英语:Deadlock),又译为死结,计算机科学名词。当两个以上的运算单元,双方都在等待对方停止运行,以获取系统资源,但是没有一方提前退出时,就称为死锁。在多任务操作系统中,操作系统为了协调不同进程,能否获取系统资源时,为了让系统运作,必须要解决这个问题。
这里指的是进程死锁,是个计算机技术名词。它是操作系统或软件运行的一种状态:在多任务系统下,当一个或多个进程等待系统资源,而资源又被进程本身或其他进程占用时,就形成了死锁。有个变种叫活锁。
例如,一个进程 p1占用了显示器,同时又必须使用打印机,而打印机被进程p2占用,p2又必须使用显示器,这样就形成了死锁。 因为p1必须等待p2发布列表机才能够完成工作并发布显示屏,同时p2也必须等待p1发布显示器才能完成工作并发布列表机,形成循环等待的死锁。
如果系统中只有一个进程,当然不会产生死锁。如果每个进程仅需求一种系统资源,也不会产生死锁。不过这只是理想状态,在现实中是可遇不可求的。
死锁的四个条件是:
禁止抢占 no preemption - 系统资源不能被强制从一个进程中退出
持有和等待 hold and wait - 一个进程可以在等待时持有系统资源
互斥 mutual exclusion - 只有一个进程能持有一个资源
循环等待 circular waiting - 一系列进程互相持有其他进程所需要的资源
死锁只有在这四个条件同时满足时出现。预防死锁就是至少破坏这四个条件其中一项,即破坏“禁止抢占”、破坏“持有等待”、破坏“资源互斥”和破坏“循环等待”。
当然小菜之前都用过简单粗暴的方法重启系统。更好的办法是终止一个进程的运行。
我们能写一个死锁吗?
思路是创建两个字符串a和b,再创建两个线程A和B,让每个线程都用synchronized锁住字符串(A先锁a,再去锁b;B先锁b,再锁a),如果A锁住a,B锁住b,A就没办法锁住b,B也没办法锁住a,这时就陷入了死锁。直接贴代码:
public class DeadLock {
public static String obj1 = "obj1";
public static String obj2 = "obj2";
public static void main(String[] args) {
Thread a = new Thread(new Lock1());
Thread b = new Thread(new Lock2());
a.start();
b.start();
}
}
class Lock1 implements Runnable {
@Override
public void run() {
try {
System.out.println("Lock1 running");
while (true) {
synchronized (DeadLock.obj1) {
System.out.println("Lock1 lock obj1");
//获取obj1后先等一会儿,让Lock2有足够的时间锁住obj2
Thread.sleep(3000);
synchronized (DeadLock.obj2) {
System.out.println("Lock1 lock obj2");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Lock2 implements Runnable {
@Override
public void run() {
try {
System.out.println("Lock2 running");
while (true) {
synchronized (DeadLock.obj2) {
System.out.println("Lock2 lock obj2");
Thread.sleep(3000);
synchronized (DeadLock.obj1) {
System.out.println("Lock2 lock obj1");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}