概念
什么是死锁?
- 个人理解:多个线程相互占据对方需要的资源,并且互相等待对方释放资源而僵持不下
- 多个线程各自占有一些公共资源,并且互相等待对方释放资源才能运行;
- 当某一个同步块同时拥有“两个以上对象的锁”时,就可能发生死锁问题,从而导致两个或多个线程都在等待对方释放资源,都停止的情况
产生死锁的四个必要条件
- 一个资源每次只能被一个线程使用(即多个线程竞争同一资源)
- 请求与保持条件:一个线程因请求资源而阻塞,对已经获得的资源保持不放
- 不剥夺条件:进程已获得的资源,在为使用完之前,不强行剥夺
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
死锁的避免方法
死锁示例
- 背景:灰姑娘和白雪公主两位?小仙女要化妆(拿着镜子涂口红),现有?、?一份
- 满足死锁的条件:
- 两位小仙女竞争?、?(资源竞争)
- 开始灰姑娘拿到?、白雪公主拿到?,然后两个小仙女等待拿到对方手里的资源(请求与保持)
- 两位小仙女礼貌且文明,不去抢夺对方手里的资源(不剥夺)
- 灰姑娘等待白雪公主手里的?,白雪公主等待灰姑娘手里的口红(循环等待)
public class DeadLock {
public static void main(String[] args) {
Girl g1=new Girl(0,"灰姑娘");
Girl g2=new Girl(1,"白雪公主");
//启动线程
g1.start();
g2.start();
}
}
//口红
class Lipstick {
}
//镜子
class Mirror{
}
//?♀️
class Girl extends Thread{
//需要的资源只有一份,用static来保证
static Lipstick lipstick=new Lipstick();
static Mirror mirror =new Mirror();
int choice; //选择
String girlName; //小仙女的名字
Girl(int choice, String girlName){
this.choice=choice;
this.girlName = girlName;
}
@Override
public void run() {
makeUp();
}
//化妆,互相持有对方的锁,即需要拿到对方的资源
private void makeUp(){
if(choice == 0){
synchronized (lipstick) { //拿到口红的锁
System.out.println(this.girlName+"获得口红的锁");
try {
Thread.sleep(1000); //睡眠1秒钟
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirror){ //一秒钟后想要获得镜子的锁
System.out.println(this.girlName + "获得镜子的锁");
}
}
}
else{
synchronized (mirror) { //拿到镜子的锁
System.out.println(this.girlName+"获得镜子的锁");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lipstick) { //1秒钟后想获得口红的锁
System.out.println(this.girlName + "获得口红的锁");
}
}
}
}
}