黑马程序员技术交流社区

标题: 关于死锁 [打印本页]

作者: 汤密奕    时间: 2012-7-8 18:18
标题: 关于死锁
本帖最后由 汤密奕 于 2012-7-9 13:24 编辑

public class DeadLine {

        /**
         * @param args
         */
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                Rescore r = new Rescore();
                Rescore r1 = new Rescore();
                r.flag=1;
                r1.flag=0;
                Thread t1 = new Thread(r);
                Thread t2 = new Thread(r1);
               
                t1.start();
                t2.start();

        }

}

class Rescore implements Runnable
{
        int flag = 1;
       Object o1 = new Object() ,o2  = new Object();   //static Object o1 = new Object() ,o2  = new Object(); ,程序死锁,不用static程序可运行结束

        public void run()
        {
               
                if(flag==1)
                {
                        synchronized(o1)
                        {
                                try {
                                        Thread.sleep(1000);
                                } catch (InterruptedException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
                                
                                synchronized(o2)
                                {
                                        for(int i = 0;i<10;i++)
                                        {
                                                System.out.println("flag=" + flag);
                                        }
                                }
                        }
                }
                if(flag==0)
                {
                        synchronized(o2)
                        {
                                try {
                                        Thread.sleep(1000);
                                } catch (InterruptedException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
                                
                                synchronized(o1)
                                {
                                        for(int i = 0;i<10;i++)
                                        {
                                                System.out.println("flag=" + flag);
                                        }
                                }
                        }
                }
               
               
        }
}

注意Object 01那行,用static修饰了会发生死锁,而去掉static,此程序不会发生死锁,为什么呢
作者: 万宝东    时间: 2012-7-8 18:43
因为Object o1 = new Object() ,o2  = new Object();   加上static修饰以后,o1和o2变成静态。
由于static 的变量所有的调用都是同一块内存(同一个进程),所以两个线程所需要的变量是一样的,那么这两个变量学名上是临介资源,一次只能给一个进程服务;
当线程1运行时,需要o1变量,此时他取得o1变量然后sleep一段时间 ,之后在线程1sleep这段时间,线程2取得变量o2,然后sleep一段时间 ,线程1sleep结束后,申请变量o2,由于线程2正控制变量o2,所以线程1无法取得,此时线程1等待线程2释放变量o2,线程1等待时未释放变量o1  ,线程2sleep结束后,申请变量o1,由于线程1正控制变量o1,所以线程2无法取得,此时线程2等待线程1释放变量o1,线程2等待时未释放变量o2   ,死锁出现了,两者都需要两个变量,而手里只有一个,等另一个,在手的又不放,则不会有一个线程能执行下去,两个就永远的这么死下去;如没有两个static变量,就不存在资源的抢夺,出现不了死锁;死锁必须存在一个以上的临介资源
作者: 胡文杰    时间: 2012-7-8 18:50
用static  类加载的时候就会创建对象,所以r和r1用的是同一个锁,但是因为锁的顺序不一样,当t1线程进入锁里面(o1),那到第一个锁而没有进入第二个锁的时候,t2线程也运行了,而且也能进入到第一个锁里面(o2) 而当t2进入到第二个锁(o1)里面的时候里面有t1,所以就进不去,当t1要进入到第二个锁(o2)里面的时候,里面有t2 所以t1获取不到第二个锁所以会出现死锁!你可以把锁的顺序调一致。而不用static 的话,t1和t2用的都不是同一个锁  也就是t1的o1,o2和t2的o1,o2 是四个不同的对象!这样写加不加static都不会出现死锁
package cn.other.java.test;

public class Rescore implements Runnable {
        int flag = 1;
    static Object o1 = new Object() ,o2  = new Object();   //static Object o1 = new Object() ,o2  = new Object(); ,程序死锁,不用static程序可运行结束

     public void run()
     {
            
             if(flag==1)
             {
                     synchronized(o1)
                     {
                             try {
                                     Thread.sleep(1000);
                             } catch (InterruptedException e) {
                                     // TODO Auto-generated catch block
                                     e.printStackTrace();
                             }
                             
                             synchronized(o2)
                             {
                                     for(int i = 0;i<10;i++)
                                     {
                                             System.out.println("flag=" + flag);
                                     }
                             }
                     }
             }
             if(flag==0)
             {
                     synchronized(o1)
                     {
                             try {
                                     Thread.sleep(1000);
                             } catch (InterruptedException e) {
                                     // TODO Auto-generated catch block
                                     e.printStackTrace();
                             }
                             
                             synchronized(o2)
                             {
                                     for(int i = 0;i<10;i++)
                                     {
                                             System.out.println("flag=" + flag);
                                     }
                             }
                     }
             }
            
            
     }

}

作者: 金龙    时间: 2012-7-8 18:58
这么跟你解释吧,所谓的同步呢,是要用的同一把锁,首先,你定义的两个没加静态的Object对象,是两个Rescore 对象的自己的,所以,不是同一把锁,连同步都做不到。
其次,死锁,是指在同步中,两个线程,A,B  。  A掌握着B的钥匙,B掌握着A的钥匙,当然,锁也要是同一个对象,你这个明显是两个对象了。而你定义的静态呢,静态修饰的成员是所有对象所共有的,所以这样,就变成了一把锁,这样就死锁了,这么说,你明白了吗




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2