死锁的避免方法:
产生死锁的四个必要条件:
1.互斥条件:一个资源每次只能被一个进程使用。
2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3.不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
4.循环等待条件:若干进程之间形成一种头尾相接的循坏等待资源关系
上面列出死锁的四个必要条件,我们只要想办法破坏其中的任意一个或者多个条件就可以避免死锁的发生。
package com.huawei.Test;
/**
* @author h84250472
* @title: Multithreading03$ 测试死锁,解决死锁
* @description: TODO
* @date 2022/8/2 10:26
*/
public class Multithreading03 {
public static void main(String[] args) {
Makeup m1 = new Makeup(0,"白雪公主");
Makeup m2 = new Makeup(1,"皇后娘娘");
new Thread(m1).start();
new Thread(m2).start();
}
}
class Lipstick{}
class Mirror{}
class Makeup implements Runnable{
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
int choose;
String name;
public Makeup(int choose, String name) {
this.choose = choose;
this.name = name;
}
@Override
public void run() {
//makeup();
make();
}
//此方法就是一个进程要获取两个对象锁,也就是口红和镜子两个资源,而另一个进程也需要获取口红和镜子两个资源
//就会导致死锁的产生
private void makeup(){
if (choose==0){
synchronized (lipstick){//获得口红锁
System.out.println(name+"获得口红锁");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirror){//获得镜子锁
System.out.println(name+"获得镜子锁");
}
}
}else {
synchronized (mirror){//获得镜子锁
System.out.println(name+"获得镜子锁");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lipstick){//获得口红锁
System.out.println(name+"获得口红锁");
}
}
}
}
//此方法是用来破坏死锁的,一个进程获得到口红锁之后,用完进行释放,在获取镜子的锁,另一个线程获取镜子锁之后,
//用完进行释放,再获取口红锁,这样就破坏了死锁
private void make() {
if (choose == 0) {
synchronized (lipstick) {//获得口红锁
System.out.println(name + "获得口红锁");
try {
//拿到口红锁之后,一秒之后再释放
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (mirror) {//获得镜子锁
System.out.println(name + "获得镜子锁");
}
} else {
synchronized (mirror) {//获得镜子锁
System.out.println(name + "获得镜子锁");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (lipstick){//获得口红锁
System.out.println(name+"获得口红锁");
}
}
}
}