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 两个线程互相等待对方先释放,所以出现了死锁。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值