现在的位置: 首页 > 综合 > 正文

死锁

2013年08月25日 ⁄ 综合 ⁄ 共 3125字 ⁄ 字号 评论关闭

 

程序中必须同时满足以下四个条件才会引发死锁:

互斥(Mutual exclusion):线程所使用的资源中至少有一个是不能共享的,它在同一时刻只能由一个线程使用。

持有与等待(Hold and wait:至少有一个线程已经持有了资源,并且正在等待获取其他的线程所持有的资源。

非抢占式(No pre-emption:如果一个线程已经持有了某个资源,那么在这个线程释放这个资源之前,别的线程不能把它抢夺过去使用。

循环等待(Circular wait):假设有N个线程在运行,第一个线程持有了一个资源,并且正在等待获取第二个线程持有的资源,而第二个线程正在等待获取第三个线程持有的资源,依此类推……第N个线程正在等待获取第一个线程持有的资源,由此形成一个循环等待。

举例:

1.未发生死锁

public class Test {   

   static Object o1 = new Object();//静态对象

   static Object o2 = new Object();   

    public static void main(String[] args) {        

         synch synch1 = new synch();

         synch synch2 = new synch();

         synch1.a=0;

         synch2.a=2;

         Thread t1 = new Thread(synch1);

         Thread t2 = new Thread(synch2);

         t1.start();

         t2.start();

    }  

}//Test类结束

class synch implements Runnable{   

    int a;

    public void run() {

        System.out.println(a);

        if(a == 0){

          try {

            synchronized (Test.o1) {//对类Testt中的静态对象同步               

                Thread.sleep(500);

            } //synchronized是对o1的对象锁,500毫秒以后会释放掉对o1的锁,所以不会发生死锁         

            synchronized (Test.o2) {

                System.out.println("aaaa");

            }

        } catch (InterruptedException ex) {}

       }else

           try {

                synchronized (Test.o2) {

                   Thread.sleep(500);

            }            

            synchronized (Test.o1) {

                System.out.println("aaba");

            }

        } catch (InterruptedException ex) {}

       

    }

}

运行后显示

0

2

aaba

aaaa

没有发生死锁

2.发生了死锁

修改如下:

public void run() {

    System.out.println(a);

    if(a == 0){

        try {

            synchronized (Test.o1) { //已获取o1对象锁

                Thread.sleep(500);

                System.out.println("Try to get o2");

                synchronized (Test.o2) {  //未释放o1(同步块中的语句执行完以后才释放该对象的锁),尝试获取o2,被挂起

                    System.out.println("aaaa");

                }

            }

        } catch (InterruptedException ex) {}

    } else {

        try {

            synchronized (Test.o2) { //已获取o2的对象锁

                Thread.sleep(500);

                System.out.println("Try to get o1");

                synchronized (Test.o1) {  //未释放o2,尝试获取o1,也被挂起,死锁

                    System.out.println("aaba");

                }

            }

        } catch (InterruptedException ex) {}

    }

}

结果:

0

2

Try to get o2

Try to get o1

另一个例子:

class Friendly {

    private Friendly partner;

    private String name;

    public Friendly(String name) {

        this.name = name;

    }

    public synchronized void hug() {

        System.out.println(Thread.currentThread().getName()+" in " + name + ".hug() trying to invoke " + partner.name +".hugBack()");

        partner.hugBack();

    }

    private synchronized void hugBack() {

        System.out.println(Thread.currentThread().getName()+" in " + name + ".hugBack()");

    }

    public void becomeFriend(Friendly partner) {

        this.partner = partner;

    }

public static void main(String[] args) {

    final Friendly jareth = new Friendly("jareth");

    final Friendly cory = new Friendly("cory");

    jareth.becomeFriend(cory);

    cory.becomeFriend(jareth);

    new Thread(new Runnable() {

        public void run() { jareth.hug(); }

    }, "Thread1").start();

 

    new Thread(new Runnable() {

        public void run() { cory.hug(); }

    }, "Thread2").start();

}

}

结果:

Thread1 in jareth.hug() trying to invoke cory.hugBack()

Thread1 in cory.hugBack()

Thread2 in cory.hug() trying to invoke jareth.hugBack()

Thread2 in jareth.hugBack()

 

抱歉!评论已关闭.