死锁:多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,这样大家就都无法继续执行。当一个同步块要同时拥有“两个以上对象的锁”时,可能会发生死锁问题
举例:
白雪公主在同步代码块中先拿口红的锁,休息10ms,不放口红的锁继续拿镜子的锁
灰姑娘在同步代码块中先拿镜子的锁,休息10ms,不放镜子的锁继续拿口红的锁
public class TestDeadLock {
public static void main(String[] args) throws InterruptedException {
new MakeUp("白雪公主",0).start();
new MakeUp("灰姑娘",1).start();
}
}
//口红
class KouHong{
}
//镜子
class Mirror{
}
class MakeUp extends Thread{
private int choice;
static private KouHong kouHong = new KouHong();
static private Mirror mirror = new Mirror();
public MakeUp(String name, int choice) {
super(name);
this.choice = choice;
}
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
void makeup() throws InterruptedException {
if(choice == 0){
synchronized (kouHong){
System.out.println(Thread.currentThread().getName()+"拿到口红");
Thread.sleep(10);
synchronized (mirror){
System.out.println(Thread.currentThread().getName()+"拿到镜子");
}
}
}else{
synchronized (mirror){
System.out.println(Thread.currentThread().getName()+"拿到镜子");
Thread.sleep(10);
synchronized (kouHong){
System.out.println(Thread.currentThread().getName()+"拿到口红");
}
}
}
}
}
产生死锁的四个必要条件,破除其中任意一个或多个就可以避免死锁:
1、互斥条件:一个资源每次只能被一个进程使用
2、请求与保持条件:一个线程请求资源被阻塞,但又对自己获得的资源保持不放
3、不剥夺条件:线程已获得的资源,在未使用完之前,不能强行剥夺
4、循环等待:若干线程之间形成一种头尾相接的循环等待资源的处境
口红镜子破解方法:
void makeup() throws InterruptedException {
if(choice == 0){
synchronized (kouHong){
System.out.println(Thread.currentThread().getName()+"拿到口红");
Thread.sleep(10);
}
synchronized (mirror){
System.out.println(Thread.currentThread().getName()+"拿到镜子");
}
}else{
synchronized (mirror) {
System.out.println(Thread.currentThread().getName() + "拿到镜子");
Thread.sleep(10);
}
synchronized (kouHong){
System.out.println(Thread.currentThread().getName()+"拿到口红");
}
}
}