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

     }
    
   }
  }
 }
 
 
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值