A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 汤密奕 初级黑马   /  2012-7-8 18:18  /  1871 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 汤密奕 于 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,此程序不会发生死锁,为什么呢

评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1

查看全部评分

3 个回复

倒序浏览
因为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变量,就不存在资源的抢夺,出现不了死锁;死锁必须存在一个以上的临介资源
回复 使用道具 举报
用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);
                                     }
                             }
                     }
             }
            
            
     }

}

评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1

查看全部评分

回复 使用道具 举报
这么跟你解释吧,所谓的同步呢,是要用的同一把锁,首先,你定义的两个没加静态的Object对象,是两个Rescore 对象的自己的,所以,不是同一把锁,连同步都做不到。
其次,死锁,是指在同步中,两个线程,A,B  。  A掌握着B的钥匙,B掌握着A的钥匙,当然,锁也要是同一个对象,你这个明显是两个对象了。而你定义的静态呢,静态修饰的成员是所有对象所共有的,所以这样,就变成了一把锁,这样就死锁了,这么说,你明白了吗
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马