死锁问题:多个线程互相拿着对方需要的资源,然后形成僵持 出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续 死锁问题的演示
package com.work; public class work6 { public static void main(String[] args) { StringBuffer s1 = new StringBuffer(); StringBuffer s2 = new StringBuffer(); //线程一 new Thread(){//用匿名内部类的方式创建线程(继承Thread类) @Override public void run() { synchronized(s1){//线程一先获得s1的锁 s1.append("a"); s2.append(1); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized(s2){//再获得s2的锁 s1.append("b"); s2.append(2); //线程一只有同时获得了s1和s2的锁才能输出s1,s2 System.out.println(s1); System.out.println(s2); } } } }.start(); //线程二 new Thread(new Runnable() {//实现Runnable接口 @Override public void run() { synchronized (s2) {//线程二先获得s2的锁 s1.append("c"); s2.append(3); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s1) {//再获得s1的锁 s1.append("d"); s2.append(4); System.out.println(s1); System.out.println(s2); } } } }).start(); } }案例二
package com.peng.demon06; import com.sun.deploy.security.SelectableSecurityManager; //死锁:多个线程互相拿着对方需要的资源,然后形成僵持 //案例背景:白雪公主,灰胡娘两个人都想化妆,但只有有个镜子和一个口红,然后一个人拿着口红,一个人拿着镜子,导致谁也化不了 public class DeadLock { public static void main(String[] args) { Makeup g1 = new Makeup(0,"白雪公主"); Makeup g2 = new Makeup(1,"灰胡娘"); g1.start(); g2.start(); } } //口红 class Lipstick{ } //镜子 class Mirror{ } //化妆的类 class Makeup extends Thread{ //化妆需要的资源就只有一份,因此用static来保证只有一份 static Lipstick lipstick = new Lipstick(); static Mirror mirror = new Mirror(); int choice;//选择 String girlName;//化妆的人名字 //构造器 public Makeup(int choice,String girlName){ this.choice=choice; this.girlName=girlName; } @Override public void run() { try { makeup(); } catch (InterruptedException e) { e.printStackTrace(); } }//化妆的方法 private void makeup() throws InterruptedException { if (choice==0){ //第一个人 synchronized (lipstick){//获得口红对象的锁 System.out.println(this.girlName+"获得口红的锁"); Thread.sleep(1000); //两个同步块在一起 synchronized (mirror){//一秒后还想获得镜子的锁 System.out.println(this.girlName+"获得镜子的锁"); } } }else { //第二个人 synchronized (mirror){//获得镜子对象的锁 System.out.println(this.girlName+"获得口红的锁"); Thread.sleep(2000); synchronized (lipstick){//2秒后还想获得口红的锁 System.out.println(this.girlName+"获得镜子的锁"); } } } } }死锁导致程序卡死
解决方法:把两个同步块分开来放,不要放在一起,不要让两个线程互相抱对方的锁
package com.peng.demon06; import com.sun.deploy.security.SelectableSecurityManager; //死锁:多个线程互相拿着对方需要的资源,然后形成僵持 public class DeadLock { public static void main(String[] args) { Makeup g1 = new Makeup(0,"白雪公主"); Makeup g2 = new Makeup(1,"灰胡娘"); g1.start(); g2.start(); } } //口红 class Lipstick{ } //镜子 class Mirror{ } //化妆的类 class Makeup extends Thread{ //化妆需要的资源就只有一份,因此用static来保证只有一份 static Lipstick lipstick = new Lipstick(); static Mirror mirror = new Mirror(); int choice;//选择 String girlName;//化妆的人名字 //构造器 public Makeup(int choice,String girlName){ this.choice=choice; this.girlName=girlName; } @Override public void run() { try { makeup(); } catch (InterruptedException e) { e.printStackTrace(); } }//化妆的方法 private void makeup() throws InterruptedException { if (choice==0){ //第一个人 synchronized (lipstick){//获得口红对象的锁 System.out.println(this.girlName+"获得口红的锁"); Thread.sleep(1000); } synchronized (mirror){//一秒后还想获得镜子的锁 System.out.println(this.girlName+"获得镜子的锁"); } }else { //第二个人 synchronized (mirror){//获得镜子对象的锁 System.out.println(this.girlName+"获得镜子的锁"); Thread.sleep(2000); } synchronized (lipstick){//2秒后还想获得口红的锁 System.out.println(this.girlName+"获得口红的锁"); } } } }产生死锁的四个必要条件
互斥条件:一个资源每次只能宝贝一个进程使用请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系我们只要想办法破其中一种或多种条件就可以避免死锁的发生