Java_浅谈死锁的产生

package day11;

 

class _15DeadLock {

  publicstaticvoid main(String[] args){

     MyTicket t=new MyTicket();

    

     //两个线程共用一个t

     Thread t1=new Thread(t);

     Thread t2=new Thread(t);

    

     //线程t1启动

扫描二维码关注公众号,回复: 10808820 查看本文章

     t1.start();

    

     try{

       Thread.sleep(10);

     }

     catch(Exception e){

      

     }

     t.flag=false;

     System.out.println("线程t2即将启动");

     //线程t2启动

     t2.start();

  }

}

class MyTicketimplements Runnable{

  privateinttick=1000;

  Object obj=new Object();

  booleanflag=true;

  publicvoid run(){

     if(flag){

       while(true){

         //同步代码块

         synchronized(obj)//class

         { //*run方法循环中的*/

           System.out.println(Thread.currentThread().getName()+"已获取run方法循环中的obj锁,尝试获取show方法锁");

            show();

           System.out.println(Thread.currentThread().getName()+"释放show方法锁");

         }

       }

     }

     else{

       while(true){

         //System.out.println("flag="+flag);

         System.out.println(Thread.currentThread().getName()+"尝试获取show方法锁");

         show();

         System.out.println(Thread.currentThread().getName()+"释放show方法锁");

       }

     }

  }

  publicsynchronizedvoid show(){//this

     System.out.println(Thread.currentThread().getName()+"已获取show方法锁,进入到show方法中,尝试获取obj");

     synchronized(obj){

       System.out.println(Thread.currentThread().getName()+"已获取show方法中obj锁,即将打印有效信息");

       if(tick>0){

         try{

            Thread.sleep(10);

         }

         catch(Exception e){

           

         }

       System.out.println(Thread.currentThread().getName()+"....code"+tick--);

       }

     }

     System.out.println(Thread.currentThread().getName()+"已释放show方法中的obj");

 

  }

}

 

某次的运行结果如下:

Thread-0已获取run方法循环中的obj锁,尝试获取show方法锁

Thread-0已获取show方法锁,进入到show方法中,尝试获取obj锁

Thread-0已获取show方法中obj锁,即将打印有效信息

线程t2即将启动

Thread-0....code1000

Thread-0已释放show方法中的obj锁

Thread-0释放show方法锁

Thread-0已获取run方法循环中的obj锁,尝试获取show方法锁

Thread-1尝试获取show方法锁

Thread-0已获取show方法锁,进入到show方法中,尝试获取obj锁

Thread-0已获取show方法中obj锁,即将打印有效信息

Thread-0....code999

Thread-0已释放show方法中的obj锁

Thread-0释放show方法锁

Thread-1已获取show方法锁,进入到show方法中,尝试获取obj锁

Thread-0已获取run方法循环中的obj锁,尝试获取show方法锁

 

   1. 从最后两行看出,一方面,Thread-1获得了show方法锁,然后尝试获取obj锁;但另一方面,Thread-0获得了obj锁,然后它尝试获取show方法锁。两个线程都在等待对方释放锁,此时造成了死锁现象。

   2.此程序中,死锁产生的具体条件是一个同步代码块中含有另一个同步方法(Thread-0执行的代码部分),而此同步方法中含有另一个同步代码块(Thread-1执行的代码部分)。即你中有我,我中有你。。。。。。

 

3.锁其实就是一个条件,类似于if 语句,但是在线程中判断条件不易用条件语句进行表达,所以用synchronized关键字表示。

同一个obj锁可以用在多处,但相互独立,这里拥有跟别处无关,因为代码块执行完,锁自动解除了。

    4.run方法中的if else就是将两个线程分开的条件。而且每个线程判断且仅判断一次。所以第一个线程判断结束后进入循环,而当主函数中flag=false执行后,随着t2.start(),第二个线程也开始运行起来,但它执行的是else里面的代码,直接要show方法锁。而此时再看看第一个线程,它是先要obj锁,然后再要show方法锁,在show方法锁获取后再次要obj锁。很显然,在线程一的运行过程中,只要能进入show方法,那么它必然可以运行show里面的方法,虽然show里还要再次获取obj锁,但是此时线程一已经获得了obj锁,所以它才能进入show方法再次要obj锁。

   5.也就是说,线程一的运行中,每次要获取锁三次,其中有两次锁是同一个的。线程二的运行中,每次要获取锁两次,其中两次的锁是不同的。这里应该明白,两个线程能死锁,并不是两个线程都是要两次锁,而是一个三次,一个两次。

   6.回过来,第二个线程的开启要凭借flag=false这一句,它让第二个线程走上了不同的运行道路,当然前提是t2.start()了。

发布了22 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/yeziyfx/article/details/38395463