您好,登录后才能下订单哦!
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 两个线程互相等待对方先释放,所以出现了死锁。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。