多線程 死鎖的產生以及解決方案

當業務比較複雜,多線程應用裏有可能會發生死鎖

死鎖產生的原因

  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();
    }
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章