java线程死锁实例

来源:互联网 发布:羞辱2优化补丁 编辑:程序博客网 时间:2024/05/16 06:55

死锁发生的四个必要条件:

    1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
    2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
    3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
    4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
上面四个条件同时成立时就会产生死锁,如果消除任何一个条件就可以消除死锁。

下面是一个死锁发生的实例:

package com.cy.test;public class Sisuo {public static Object object1;public static Object object2;public static class MyRunnable implements Runnable {int flag;public MyRunnable(int flag) {this.flag = flag;}@Overridepublic void run() {if (flag == 1) {synchronized (object1) {for(int i=0;i<10000;i++);//扩大死锁发生几率//或者Thread.sleep(50);synchronized (object2) {System.out.println("1");}}} else if (flag == 2) {synchronized (object2) {for(int i=0;i<10000;i++);//或者Thread.sleep(50);synchronized (object1) {System.out.println("2");}}}}}public static void main(String[] args) {object1 = new Object();object2 = new Object();new Thread(new MyRunnable(1)).start();new Thread(new MyRunnable(2)).start();}}
上面的实例在运行时会发生死锁,也就是两个线程分别等待另一个线程释放资源,但另一个线程被synchronized关键字修饰,不能直接释放资源,所以造成的结果就是相互等待,程序直接挂掉了。

下面主要分析一下发生死锁的原因:

从上面的程序来看,改程序主要使用了两把锁,分别是线程1对资源object1占有资源的同时又对object2申请资源,并想占有,同时线程2对资源object2占有资源的同时又对object1申请资源,如果我们删除两个锁之间的循环语句,最后得到的结果可能是能正常运行的,那么为什么这种情况没有死锁呢,其实是因为cpu的运行速度非常快,此时线程1占有了资源object1,并很快又占据资源object2,此时线程2想要申请object2的时候,资源已经被线程1占有,所以此时等待线程1执行完毕,最后输出的结果就会是12或者21,但是如果在两个锁之间加了运算稍微大的运算,那么最后的结果就是线程1已经占据资源object1,线程2已经占据资源object2,此时线程1申请资源object2时,已经被线程2占有,而此时线程2申请资源object1时又被线程1占有,此时两者都不能释放各自占有的资源,因为用synchronized关键字所修饰,所以最后的结果就会是相互等待而系统直接挂掉


0 0
原创粉丝点击