关于线程死锁以及如何避免产生死锁总结

死锁概念:在多个线程同时被阻塞时,它们之间若互相等待对方释放资源,就会出现死锁。

public class ThreadDemo_01 {
    private static Object resource1=new Object();  //资源1
    private static Object resource2=new Object();   //资源2
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resource1){
                    System.out.println(Thread.currentThread()+"get resource1");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread()+"waiting get resource2");
                         synchronized (resource2){
                             System.out.println(Thread.currentThread()+"get resource2");
                         }
                }
            }
        },"线程 1").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resource2){
                    System.out.println(Thread.currentThread()+"get resource2");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread()+"waiting get resource1");
                         synchronized (resource1){
                             System.out.println(Thread.currentThread()+"get resource1");
                         }
                }
            }
        },"线程 2").start();
    }
}

产生死锁必须具备的四个条件:

  1. 互斥条件:该资源任意一个时刻只有一个线程占用。
  2. 请求与保持条件:一个进程因请求资源而被阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。
  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
    如何避免产生线程死锁?
  5. 破坏互斥条件 :这个条件无法破坏,因为我们用索本来就是想让它们互斥。
  6. 破坏请求与保持条件:一次性申请所以的资源。
  7. 破坏不剥夺条件:占用部门的资源线程进一步申请其他资源,如果申请不到,可用主动释放它占用的资源。
  8. 破坏循环等待条件:靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。

修改代码不产生死锁:

public class StringDemo_01 {
    private static Object resource1=new Object();
    private static Object resource2=new Object();

    public static void main(String[] args) {


        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resource1){
                    System.out.println(Thread.currentThread()+"get resource1");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread()+"waiting get resource2");
                         synchronized (resource2){
                             System.out.println(Thread.currentThread()+"get resource2");
                         }
                }
            }
        },"线程 1").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resource1){
                    System.out.println(Thread.currentThread()+"get resource1");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread()+"waiting get resource2");
                         synchronized (resource2){
                             System.out.println(Thread.currentThread()+"get resource2");
                         }
                }
            }
        },"线程 2").start();
    }
}

解释原因:线程1首先获得到resource1的监视器锁,这个时候线程2就获取不到了。然后线程1再去获取resource2的监视器锁,可以获取到。然后线程1释放了对resource1、resource2的监视器锁的占用,线程2获取到就可以执行了。这样就破坏了循环等待条件,因为避免了死锁。

你可能感兴趣的:(并发编程,多线程,java,并发编程)