class Synchronized implements Runnable
{
private boolean flag;
Synchronized (boolean flag)
{
this.flag=flag;
}
public void run()
{
if (flag==true)
{
synchronized(LockDemo.a)
{
System.out.println("a锁第一层");
synchronized(LockDemo.b)
{
System.out.println("a锁第二层");
}
}
}
else
synchronized(LockDemo.b)
{
System.out.println("b锁第一层");
synchronized(LockDemo.a)
{
System.out.println("b锁第二层");
}
}
}
}
class LockDemo
{
static LockDemo a=new LockDemo();
static LockDemo b=new LockDemo();
}
class LockDemo1
{
public static void main(String[] args)
{
Synchronized s=new Synchronized(true);
Synchronized s1=new Synchronized(false);
Thread t=new Thread(s);
Thread t1=new Thread(s1);
t.start();
t1.start();
}
}
我觉得s和s1不是2个对象么?那么线程t操作s对象  线程t1操作s1对象 两个线程操作的是两个不同对象它们两个怎么会有影响呢?

解决方案 »

  1.   

    关键在于这两个对象共同操作了:
    static LockDemo a=new LockDemo();
    static LockDemo b=new LockDemo();其中一个是用:
    synchronized(LockDemo.a) {
      System.out.println("a锁第一层");
      synchronized(LockDemo.b)
    这种方式先锁住a,再锁住b。
    而另一个使用:
    synchronized(LockDemo.b) {
      System.out.println("b锁第一层");
      synchronized(LockDemo.a)
    这种方式先锁住b,在锁住a。
    所以就死锁了。
    s、s1两个小朋友,a、b两个水果。s抢了a,还要b;s1抢了b,还要a。
      

  2.   

    我不理解的地方是,t操作s对象 线程t1操作s1对象,他们两个对象怎么就有联系了?   怎么样理解才能理解成 线程t和t1在操作同一个对象?或者说,我感觉如果t和t1操作的是同一个对象就好理解了。
      

  3.   

    你好像理解乱了吧线程t操作s对象,s对象操作了 a 和 b;
    线程t1操作s1对象,s1对象操作了 b 和 a;他们之间的联系是建立在:ab 上的。
    这是一个亲子游乐场,举行抢水果比赛,于是:
    母亲t,要求她的小孩s,去抢得两个水果a和b;
    母亲t1,要求她的小孩s1,去抢得两个水果a和b;结果s先抢到了a,s1先抢到了b;但这都不算赢,所以他们死守住自己水果的同时,要拼命去抢对方的水果
      

  4.   

    Synchronized s=new Synchronized(true);
    Synchronized s1=new Synchronized(false);不是两个new么?我理解成2个游乐场,游乐场一。内母亲t要求小孩s去抢      游乐场二。母亲t1要求小孩抢感觉没什么关系啊。是哪一步理解错了?
      

  5.   

    抢啥东西理解错了你要注意他们抢的都是LockDemo中的static成员:a 和 b,这是全JVM唯一的:
    class LockDemo {
      static LockDemo a=new LockDemo();
      static LockDemo b=new LockDemo();
    }
    不是你说的:
    Synchronized s=new Synchronized(true);
    Synchronized s1=new Synchronized(false);
    这两个只是执行者,是(Runnable):
    class Synchronized implements Runnable {
    无非可能是名字叫Synchronized显得比较不好,跟同步关键字长得很像,所以容易引起误会,建议把这个类的名字改为:Worker之类的。
    真正执行了“抢占”动作的语句是:
    synchronized(LockDemo.a) 和 synchronized(LockDemo.b)
      

  6.   

    游乐场1内,  小孩s抢了a还想抢b   
    游乐场2内    小孩s1抢了b还想抢a 
    而a 和b是两个游乐场公有的。  
    不知道是不是可以这么理解?
    如果不是同一个游乐场  为啥还要new  2个
    Synchronized s=new Synchronized(true);
    Synchronized s1=new Synchronized(false);
      

  7.   

    就理解为科学家拿筷子问题。科学家围成一桌,每个科学家之间只有1只筷子。结果每个科学家都拿着左手边筷子不放手,结果都饿死了。
    该问题也是一样的。
    new了两只筷子a,b。new了两个人s,s1.
    规则是 拿到两个锁之后就可以线程结束释放锁,就是拿到两种筷子吃完饭,筷子洗一下别人又可以用了。
    结果s拿着a筷子不放,b拿着b筷子不放,结果两个人都吃不了饭,资源释放不了,产生死锁。
      

  8.   

    class Person implements Runnable
    {
    /*static*/ LockDemo b=new LockDemo();
    /*static*/ LockDemo a=new LockDemo();
    private boolean flag;
    Person (boolean flag)
    {
    this.flag=flag;
    }
    public void run()
    {
    if (flag==true)
    {
    synchronized(LockDemo.a)
    {
    System.out.println("a锁第一层");
    synchronized(LockDemo.b)
    {
    System.out.println("a锁第二层");
    }
    }
    }
    else
    synchronized(LockDemo.b)
    {
    System.out.println("b锁第一层");
    synchronized(LockDemo.a)
    {
    System.out.println("b锁第二层");
    }
    }
    }
    }class LockDemo1
    {
    public static void main(String[] args)
    {
    Person s=new Person(true);
    Person s1=new Person(false);
    Thread t=new Thread(s);
    Thread t1=new Thread(s1);
    t.start();
    t1.start();
    }
    }
    我想应该这么问 , 就是以上程序注释部分的static 写着后再运行和不写后再运行结果的区别在哪里,为什么会造成这样的区别。(感觉有点老师在质问学生的感觉,小弟初学者,表达能力也不好望各位大哥谅解)。
      

  9.   

    我觉得你的理解在层次剖析上始终有点问题。1、游乐场是环境,我认为你能将其视同为游乐场的,只能是“JVM”了。2、对Synchronized这个类定位也不准:
    class Synchronized implements Runnable
    它实现了接口Runnable,从这个语义上来说,它只能是个执行者,有主观能动性才行。游乐场有主观能动性么?
    public void run()函数就是它的主要动作内容,或者说执行内容。3、被抢的是资源,资源受环境所管辖,且自身也不具备主观能动性,在这个理解下:
    static LockDemo a=new LockDemo();
    static LockDemo b=new LockDemo();
    是符合该特性的。4、Thread t=new Thread(s); 那这是啥?
    只能理解为许可性的内容,其start()相当于让Runnable这个执行者开始执行其动作。
    那么可以理解为:进游乐场玩抢资源的门票 或者 母亲的命令。
      

  10.   

    你把你那
    static LockDemo a = new LockDemo();
    static LockDemo b = new LockDemo();
    改成
            LockDemo a = new LockDemo();
    LockDemo b = new LockDemo();
    就和你一开始想的一样。如果是
    static LockDemo a = new LockDemo();
    static LockDemo b = new LockDemo();
    你那样理解是错的去了解下static
      

  11.   

    是的把static去掉就和我想的是一样的,我想问的是static在这起的作用是什么?
      

  12.   


    这么改后,这程序就没法编译了:
    synchronized(LockDemo.a)
    只能对静态成员这样引用。另外,楼主同学,我5楼说了:
    你要注意他们抢的都是LockDemo中的static成员:a 和 b,这是全JVM唯一的:
    class LockDemo {
      static LockDemo a=new LockDemo();
      static LockDemo b=new LockDemo();
    }
      

  13.   

    class Person implements Runnable
    {
    /*static*/ LockDemo b=new LockDemo();
    /*static*/ LockDemo a=new LockDemo();
    private boolean flag;
    Person (boolean flag)
    {
    this.flag=flag;
    }
    public void run()
    {
    if (flag==true)
    {
    synchronized(LockDemo.a)
    {
    System.out.println("a锁第一层");
    synchronized(LockDemo.b)
    {
    System.out.println("a锁第二层");
    }
    }
    }
    else
    synchronized(LockDemo.b)
    {
    System.out.println("b锁第一层");
    synchronized(LockDemo.a)
    {
    System.out.println("b锁第二层");
    }
    }
    }
    }
    class LockDemo1
    {
    public static void main(String[] args)
    {
    Person s=new Person(true);
    Person s1=new Person(false);
    Thread t=new Thread(s);
    Thread t1=new Thread(s1);
    t.start();
    t1.start();
    }
    }
    我指的是这个程序里跟上面那个不一样,改过了。
      

  14.   

    你这个修改后,相当于每个Person implements Runnable自己就拥有:
    /*static*/ LockDemo b=new LockDemo();
    /*static*/ LockDemo a=new LockDemo();
    两个苹果(对象级的成员变量)。既然不存在对同一个资源的竞争,当然相互之间就完全没任何关系,当然不可能死锁。
    根本都不需要写类名:
    synchronized(LockDemo.a)
    你直接这么写就行了:
    synchronized(a);
    或者:
    synchronized(b);
    static代表该变量为类静态变量,是该类所生成的所有对象所共享的。
      

  15.   

    哦,可以这么理解么?
    static LockDemo a = new LockDemo();
    static LockDemo b = new LockDemo();
    存在于方法区中并不是每一个对象里都有的,这是全JVM唯一的:
    synchronized(LockDemo.a)
    {
       System.out.println("a锁第一层");
       synchronized(LockDemo.b)
       {
         System.out.println("a锁第二层");
       }
    }
    所以当s操作到这个第二层时需要方法区中b的锁但是此时b锁是锁着的
    synchronized(LockDemo.b)
    {
         System.out.println("b锁第一层");
         synchronized(LockDemo.a)
         {
           System.out.println("b锁第二层");
         }

    当s1操作到这个第二层时需要方法区中a的锁 但此时a锁是锁着的