您的位置:首页 > 编程语言 > Java开发

JAVA最直观的死锁代码

2017-11-12 19:56 190 查看
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);

      

     }

    

   }

  }

 }

 

 

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息