java實現死鎖和部分解決方法演示

死鎖簡介:


  定義:多個線程同時等待其他線程釋放鎖,導致被無限期阻塞
  原因

  • A線程持有鎖1,這時主內存的鎖1變量進入鎖定狀態,其他想獲得此變量的的線程必須等待。B線程持有鎖2,主內存中的鎖2變量進入鎖定狀態。
  • 這時A線程再去獲取鎖2,B線程再去獲取鎖1,而此時A、B線程都沒有對原先鎖變量進行解鎖,故A線程等待B線程釋放鎖2,而B線程等待A線程釋放鎖1。
  • 這時就出現了A、B線程同時被無限期阻塞,故導致死鎖

代碼實現:

package com.yitian.lock;

/**
 * @Description TODO 實現死鎖
 * @Author yitianRen
 * @Date 2019/7/25 15:18
 * @Version 1.0
 **/
public class DeadLock {
    protected static String locak1="1";
    protected static String locak2="2";


    public static void main(String[] args) {
        Thread thread1=new Thread(new lock1());
        Thread thread2=new Thread(new lock2());
        thread1.start();
        thread2.start();
    }


}

class lock1 implements Runnable{
    @Override
    public void run() {
        synchronized (DeadLock.locak1){
            System.out.println("lock1:我獲得了第一個🔒");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (DeadLock.locak2){
                System.out.println("lock1:我獲得了第二個🔒");
            }
        }
    }
}

class lock2 implements Runnable{
    @Override
    public void run() {
        synchronized (DeadLock.locak2){
            System.out.println("lock2:我獲得了第一個🔒");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (DeadLock.locak1){
                System.out.println("lock2:我獲得了第二個🔒");
            }
        }
    }
}

  避免方法

  • 加鎖順序:上述例子出現死鎖因爲A、B線程加鎖的順序不同,如果按照相同順序,則可以避免死鎖
 public static void main(String[] args) {
        Thread thread1 = new Thread(new lock1());
        Thread thread2 = new Thread(new lock2());
        thread1.start();
        try {
            thread1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread2.start();


    }
  • 加鎖時限:給鎖加一個超時時間,若一個線程沒有在給定的時限內成功獲得所有需要的鎖,則會進行回退並釋放所有已經獲得  的鎖,然後等待一段隨機的時間再重試。(  注:這種機制存在一個問題,在Java中不能對synchronized同步塊設置超時時間。你需要創建一個自定義鎖,或使用Java5中java.util.concurrent包下的工具)
  • 死鎖檢測:死鎖檢測是一個更好的死鎖預防機制,它主要是針對那些不可能實現按序加鎖並且鎖超時也不可行的場景。(注: 還是上述例子,線程A持有鎖1,請求鎖2,線程B持有鎖2,請求鎖1。這時可以讓線程A去檢測線程B是否已經請求了線程A當前鎖持有的鎖,如果線程B的確是在請求,則線程A取消請求,並釋放鎖1,回退和等待。當然現實可能多條線程交叉,它需要遞進地檢測。)

阻塞線程簡單實現

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