JAVA最直觀的死鎖代碼

package com.sunle.thread;

import java.util.ArrayList;

import com.sunle.object;
/**
 * 死鎖:
 * 就是兩個同時在運行的線程,他們在擁有自己的對象同時,又要互相訪問資源。
 * 這時同步機制就發揮了作用,導致它們都開始等待對方先執行完,而雙方都要做的
 * 卻是訪問對方鎖定的資源,這樣就進入了線程死衚衕。
 *
 *
 * 1.利用多線程在同步關鍵字synchronized()鎖定容器ArrayList對象,
 * 在進行增加和移除時出現的死鎖問題。
 *
 * 2.針對問題1,用代碼將它問題結果最直觀的展現出來。
 *
 * 3.通過結果顯示得出結論:當多個同步鎖同時鎖住一個對象的情況下,
 * 會出現
 * @author 孫樂
 *
 */
public class SynDeadLockT {
 public static void main(String[] args){
 ArrayList arr1;
 ArrayList arr2;
 arr1=new ArrayList<>();
 arr2=new ArrayList<>();

 Test t=new Test();
 t.setArrA(arr1);
 t.setArrB(arr2);
 
 Thread th1=new Thread(t,"--th1--");
 Thread th2=new Thread(t,"--th2--");
 th1.start();
 th2.start();
 
 }

}
class Test implements Runnable{
 private ArrayList arrA;
 private ArrayList arrB;
 private String str1="--th1--";
 private String str2="--th2--";
 int j=0;
 public ArrayList getArrA() {
  return arrA;
 }

 public void setArrA(ArrayList arrA) {
  this.arrA = arrA;
 }

 public ArrayList getArrB() {
  return arrB;
 }

 public void setArrB(ArrayList arrB) {
  this.arrB = arrB;
 }


 
 public void run(){
  arrAdd();
 
  arrDel();
  
 }
 
 //ArrayList增加數據方法,利用同步鎖,鎖住了操作對象的代碼塊
 private void arrAdd(){
  synchronized (arrA) {
  //1t,2t
   System.out.println(str1.equals(Thread.currentThread().getName()));
   System.out.println(str2.equals(Thread.currentThread().getName()));
   
   //arrB添加數據代碼塊,根據先後進入的線程,對容器對象進行添加數據的控制。
   for(int i=0;i<5;i++){
    if(j==5&&j<6){
     /*如果打印的是1表示已經new了一個新的容器對象,並且容器裏面沒有數據。
      *  並且CPU已經執行完了前面的線程,釋放了之前地址,JVM回收了之前的收對象*/
     
     /*1.若打印的是地址,並且和下面del方法出現的是同一個地址,
      *  那麼證明CPU尚未執行完前線程一,只是cpu分配給線程一的
      *  時間片段已經用完,線程一的狀態是等待cpu再次運行時間片,
      *  這時線程二開始了它的執行。
      * 
      * 2.這時線程一和線程二都擁有調度arrA和arrB的權限,只是
      * 這時的線程一已經執行到刪除方法在等CPU,線程一鎖住的對象arrB裏還含有
      * 另一個同步對象arrA的鎖,正好線程二正在調度的是arrA的同步鎖,
      * 而線程二里也有arrB的同步鎖
      *
      * 3.接下來當線程二執行將要調度arrB時,發現線程一還未執行完arrB,那麼
      * 線程二就開始等待線程一執行完,
      * 接着線程一便開始執行,但是當它執行到arrA時,又發現線程二還未
      * 執行完arrA,這時線程一也開始了等待,兩個線程就開始了漫長的互相等待*/
     
     System.out.println("add方法監聽A的地址1:"+arrA.hashCode()+Thread.currentThread().getName());
    }
    arrA.add(Thread.currentThread().getName());
    if(str1.equals(Thread.currentThread().getName())&&arrA.size()>5){
     
    System.out.println(arrA.get(arrA.size()-i-1)+"添加方法A");
    }else if(str2.equals(Thread.currentThread().getName())&&arrA.size()>5){
     System.out.println(arrA.get(arrA.size()-i-1)+"添加方法A");
    }else{
     if(j==5){
      //如果不是同一個對象,這裏將打印新對象的地址,程序就不會死鎖。
      System.out.println("Add方法監聽A的地址2:"+arrA.hashCode()+Thread.currentThread().getName());
     }
     System.out.println(arrA.get(i)+"添加方法A");
     
    }
    j++;
   }
   System.out.println(arrA.size()+"容器長度---J="+j);
   
   
   synchronized (arrB) {
    //arrB添加數據,和arrA添加數據是一個模型
    for(int i=0;i<5;i++){
     arrB.add(Thread.currentThread().getName());
     if(str1.equals(Thread.currentThread().getName())&&arrB.size()>5){
      
     System.out.println(arrB.get(arrB.size()-i-1)+"添加方法B");
     }else if(str2.equals(Thread.currentThread().getName())&&arrB.size()>5){
      System.out.println(arrB.get(arrB.size()-i-1)+"添加方法B");
     }else{
      System.out.println(arrB.get(i)+"添加方法B");
     }
    } 
    
    
   }

   }

 

 }
 //ArrayList移除數據方法,利用同步鎖,鎖住了操作對象的代碼塊
 public void arrDel(){

   synchronized(arrB){
    /*監聽容器arrA在上一個方法增加完數據之後,在本移除方法裏即將執行synchronied代碼塊
     * 之前打印的容器arrA的地址,它打印的是按CPU先後順序執行的線程。-----下面註釋提示----*/
    System.out.println("Del方法監聽A的地址:"+arrA.hashCode()+Thread.currentThread().getName());
    
    for(int i=0;arrB.size()>0;i++){
     
     System.out.println(arrB.get(arrB.size()-1)+Thread.currentThread().getName()+"刪除B");
     arrB.remove(arrB.size()-1);
     try {
      Thread.sleep(500);
     } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
     
     
    }
    /*-------------上一個註釋,指的是這裏-----------爲直觀展示---------*/
    synchronized(arrA){
     for(int i=0;arrA.size()>0;i++){
      System.out.println(arrA.get(arrA.size()-1)+Thread.currentThread().getName()+"刪除A");
      arrA.remove(arrA.size()-1);
      

     }
    
   }
  }
 }
 
 
}

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