欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java中死锁的原理实战分析

程序员文章站 2023-11-24 20:47:58
本文实例讲述了java中死锁的原理。分享给大家供大家参考,具体如下: 一 点睛 当两个线程相互等待对方释放同步监视器时就会发生死锁,java虚拟机没有监测、也没有采用措...

本文实例讲述了java中死锁的原理。分享给大家供大家参考,具体如下:

一 点睛

当两个线程相互等待对方释放同步监视器时就会发生死锁,java虚拟机没有监测、也没有采用措施来处理死锁情况,所以多线程编程时应该采取措施避免死锁的出现。

一旦出现死锁,整个程序既不会发生任何异常,也不会给出任何提示,只是所有线程处于阻塞状态,无法继续。

二 代码

class a
{
   public synchronized void foo( b b )
   {
      system.out.println("当前线程名: " + thread.currentthread().getname()
        + " 进入了a实例的foo()方法" );   // ①
      try
      {
        thread.sleep(200);
      }
      catch (interruptedexception ex)
      {
        ex.printstacktrace();
      }
      system.out.println("当前线程名: " + thread.currentthread().getname()
        + " 企图调用b实例的last()方法");  // ③
      b.last();
   }
   public synchronized void last()
   {
      system.out.println("进入了a类的last()方法内部");
   }
}
class b
{
   public synchronized void bar( a a )
   {
      system.out.println("当前线程名: " + thread.currentthread().getname()
        + " 进入了b实例的bar()方法" );  // ②
      try
      {
        thread.sleep(200);
      }
      catch (interruptedexception ex)
      {
        ex.printstacktrace();
      }
      system.out.println("当前线程名: " + thread.currentthread().getname()
        + " 企图调用a实例的last()方法"); // ④
      a.last();
   }
   public synchronized void last()
   {
      system.out.println("进入了b类的last()方法内部");
   }
}
public class deadlock implements runnable
{
   a a = new a();
   b b = new b();
   public void init()
   {
      thread.currentthread().setname("主线程");
      // 调用a对象的foo方法
      a.foo(b);
      system.out.println("进入了主线程之后");
   }
   public void run()
   {
      thread.currentthread().setname("副线程");
      // 调用b对象的bar方法
      b.bar(a);
      system.out.println("进入了副线程之后");
   }
   public static void main(string[] args)
   {
      deadlock dl = new deadlock();
      // 以dl为target启动新线程
      new thread(dl).start();
      // 调用init()方法
      dl.init();
   }
}

三 运行结果

当前线程名: 主线程 进入了a实例的foo()方法
当前线程名: 副线程 进入了b实例的bar()方法
当前线程名: 主线程 企图调用b实例的last()方法
当前线程名: 副线程 企图调用a实例的last()方法

四 说明

从运行结果来看,程序无法向下执行,也不会抛出任何异常,就一直“僵持”者。

上面代码中的a对象和b对象的方法都是同步方法,也就是a对象和b对象都是同步锁。

程序中有两个线程执行,一个线程的线程执行体是deadlock类的run()方法,另外一个是deadlock的init()方法(主线程调用init()方法)。其中run()方法让b对象调用bar()方法,而init()方法让a对象调用foo()方法。

程序运行的流程如下:

  • 1 init()方法先执行,调用a对象的foo()方法,进入foo()方法之前,该线程对a对象加锁,进入foo()方法后,打印一下,然后暂停执行200ms
  • 2 cpu切换到另外一个线程,让b对象执行bar方法,进入bar()方法之前,该线程对b对象加锁,进入bar()方法后,打印一下,然后暂停执行200ms
  • 3 主线程先醒过来,继续向下执行,当调用b对象的last方法时,会被阻塞,因为此时必须对b对象进行加锁,但此时副线程正保持b对象的锁,所以此时主线程会一直等待。
  • 4 副线程会醒过来,会继续往下执行,当调用a对象的last方法时,会被阻塞,因为此时必须对a对象加锁,但此时主线程正保持a对象的锁,所以此时副线程会一直等待。
  • 5 两个线程互相等待对方先释放,所以出现了死锁。

更多java相关内容感兴趣的读者可查看本站专题:《java进程与线程操作技巧总结》、《java数据结构与算法教程》、《java操作dom节点技巧总结》、《java文件与目录操作技巧汇总》和《java缓存操作技巧汇总

希望本文所述对大家java程序设计有所帮助。