当业务比较复杂,多线程应用里有可能会发生死锁

死锁产生的原因

  1. 线程1 首先占有对象1,接着试图占有对象2
  2. 线程2 首先占有对象2,接着试图占有对象1
  3. 线程1 等待线程2释放对象2
  4. 与此同时,线程2等待线程1释放对象1
    就会。。。一直等待下去,直到永远循环下去。

代码演示形成死锁

package multiplethread;
import charactor.Hero;
public class TestThread5 {
    public static void main(String[] args) {
        final Hero ahri = new Hero();
        ahri.name = "九尾妖狐";
        final Hero annie = new Hero();
        annie.name = "安妮";
         
        Thread t1 = new Thread(){
            public void run(){
                //占有九尾妖狐
                synchronized (ahri) {
                    System.out.println("t1 已占有九尾妖狐");
                    try {
                        //停顿1000毫秒,另一个线程有足够的时间占有安妮
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println("t1 试图占有安妮");
                    System.out.println("t1 等待中 。。。。");
                    synchronized (annie) {
                        System.out.println("do something");
                    }
                }  
                 
            }
        };
        t1.start();
        Thread t2 = new Thread(){
            public void run(){
                //占有安妮
                synchronized (annie) {
                    System.out.println("t2 已占有安妮");
                    try {
                         
                        //停顿1000毫秒,另一个线程有足够的时间占有暂用九尾妖狐
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println("t2 试图占有九尾妖狐");
                    System.out.println("t2 等待中 。。。。");
                    synchronized (ahri) {
                        System.out.println("do something");
                    }
                }  
                 
            }
        };
        t2.start();
   }      
}

借助tryLock 解决死锁问题

当多个线程按照不同顺序占用多个同步对象的时候,就有可能产生死锁现象。

死锁之所以会发生,就是因为synchronized 如果占用不到同步对象,就会苦苦的一直等待下去,借助tryLock的有限等待时间,解决死锁问题

package multiplethread;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestThread13 {
    public static void main(String[] args) throws InterruptedException {
        Lock lock_ahri = new ReentrantLock();
        Lock lock_annie = new ReentrantLock();
  
        Thread t1 = new Thread() {
            public void run() {
                // 占有九尾妖狐
                boolean ahriLocked = false;
                boolean annieLocked = false;
                  
                try {
                    ahriLocked = lock_ahri.tryLock(10, TimeUnit.SECONDS);
                    if (ahriLocked) {
                        System.out.println("t1 已占有九尾妖狐");
                        // 停顿1000秒,另一个线程有足够的时间占有安妮
                        Thread.sleep(1000);
                        System.out.println("t1 试图在10秒内占有安妮");
                        try {
                            annieLocked = lock_annie.tryLock(10, TimeUnit.SECONDS);
                            if (annieLocked)
                                System.out.println("t1 成功占有安妮,开始啪啪啪");
                            else{
                                System.out.println("t1 老是占用不了安妮,放弃");
                            }
  
                        } finally {
                            if (annieLocked){
                                System.out.println("t1 释放安妮");
                                lock_annie.unlock();
                            }
                        }
  
                    }
                } catch (InterruptedException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } finally {
                    if (ahriLocked){
                        System.out.println("t1 释放九尾狐");
                        lock_ahri.unlock();
                    }
                }
  
            }
        };
        t1.start();
          
        Thread.sleep(100);
          
        Thread t2 = new Thread() {
            public void run() {
                boolean annieLocked = false;
                boolean ahriLocked = false;
                                  
                try {annieLocked = lock_annie.tryLock(10, TimeUnit.SECONDS);
                  
                if (annieLocked){
                      
                        System.out.println("t2 已占有安妮");
                        // 停顿1000秒,另一个线程有足够的时间占有安妮
                        Thread.sleep(1000);
                        System.out.println("t2 试图在10秒内占有九尾妖狐");
                        try {
                            ahriLocked = lock_ahri.tryLock(10, TimeUnit.SECONDS);
                            if (ahriLocked)
                                System.out.println("t2 成功占有九尾妖狐,开始啪啪啪");
                            else{
                                System.out.println("t2 老是占用不了九尾妖狐,放弃");
                            }
                        }
                        finally {
                            if (ahriLocked){
                                System.out.println("t2 释放九尾狐");
                                lock_ahri.unlock();
                            }
                                  
                        }
  
                    }
                } catch (InterruptedException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } finally {
                    if (annieLocked){
                        System.out.println("t2 释放安妮");
                        lock_annie.unlock();
                    }
                          
                }
            }
        };
        t2.start();
    }
}