死锁
多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情景,某一个代码块同时拥有两个或者两个以上的锁时,就会发生死锁的问题
死锁就是多个线程互相持有对方所需要的资源,形成僵持,谁也拿不到
代码实现死锁
package com.wyh.thread; import org.omg.PortableServer.THREAD_POLICY_ID; import java.awt.*; /** * @program: Thread * @description: 死锁测试 * @author: 魏一鹤 * @createDate: 2022-01-16 18:34 **/ //死锁:多个线程互相持有对方所需要的资源,形成僵持,谁也拿不到 public class DeadLock { public static void main(String[] args){ //实例化两个女生去拿资源 MakeUp makeUp1=new MakeUp(0,"灰姑娘"); MakeUp makeUp2=new MakeUp(1,"白雪公主"); //开启执行方法 makeUp1.start(); makeUp2.start(); } } //口红 class Lipstick{ } //镜子 class Mirror{ } //化妆 class MakeUp extends Thread{ //需要使用到的资源只有一份,用static只有一份 static Lipstick lipstick=new Lipstick(); static Mirror mirror=new Mirror(); //选择 int choose; //使用化妆品的人 String name; //有参数的构造方法 MakeUp(int choose,String name){ this.choose = choose; this.name = name; } //继承Thread重写run方法 @Override public void run() { //化妆 try { makeUp(); } catch (InterruptedException e) { e.printStackTrace(); } } //化妆方法,互相持有对方的锁,就是拿到对方的资源 private void makeUp() throws InterruptedException { if(choose==0){ //获得口红的锁 synchronized (lipstick) { System.out.println(this.name+"获得口红的锁"); //获得之后阻塞1s Thread.sleep(1000); //1s后想获得镜子 synchronized (mirror) { System.out.println(this.name+"获得镜子的锁"); } } }else{ //获得口红的锁 synchronized (mirror) { System.out.println(this.name+"获得镜子的锁"); //获得之后阻塞1s Thread.sleep(2000); //2s后想获得口红 上面是一秒这里改为两秒 保证可以获取到资源 synchronized (lipstick) { System.out.println(this.name+"获得口红的锁"); } } } } }
解决死锁,把synchronized代码块拿出来放到外面,不同时获得多个资源
package com.wyh.thread; import org.omg.PortableServer.THREAD_POLICY_ID; import java.awt.*; /** * @program: Thread * @description: 死锁测试 * @author: 魏一鹤 * @createDate: 2022-01-16 18:34 **/ //死锁:多个线程互相持有对方所需要的资源,形成僵持,谁也拿不到 public class DeadLock { public static void main(String[] args){ //实例化两个女生去拿资源 MakeUp makeUp1=new MakeUp(0,"灰姑娘"); MakeUp makeUp2=new MakeUp(1,"白雪公主"); //开启执行方法 makeUp1.start(); makeUp2.start(); } } //口红 class Lipstick{ } //镜子 class Mirror{ } //化妆 class MakeUp extends Thread{ //需要使用到的资源只有一份,用static只有一份 static Lipstick lipstick=new Lipstick(); static Mirror mirror=new Mirror(); //选择 int choose; //使用化妆品的人 String name; //有参数的构造方法 MakeUp(int choose,String name){ this.choose = choose; this.name = name; } //继承Thread重写run方法 @Override public void run() { //化妆 try { makeUp(); } catch (InterruptedException e) { e.printStackTrace(); } } //化妆方法,互相持有对方的锁,就是拿到对方的资源 private void makeUp() throws InterruptedException { if(choose==0){ //获得口红的锁 synchronized (lipstick) { System.out.println(this.name+"获得口红的锁"); //获得之后阻塞1s Thread.sleep(1000); } //1s后想获得镜子 synchronized (mirror) { System.out.println(this.name+"获得镜子的锁"); } }else{ //获得口红的锁 synchronized (mirror) { System.out.println(this.name+"获得镜子的锁"); //获得之后 阻塞1s Thread.sleep(2000); } //2s后想获得口红 上面是一秒这里改为两秒 保证可以获取到资源 synchronized (lipstick) { System.out.println(this.name+"获得口红的锁"); } } } }
产生死锁的四个必要条件
- 互斥条件:一个资源每次只能被一个进行使用
- 请求与保持条件:一个进程因请求资源而阻塞时,对已经获得资源保持不放
- 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
如何解决死锁
一种是用synchronized,一种是用Lock显式锁实现
也可以进行时间限制,在规定的时间内,如果可以获取到锁就得到,获取不到就算了