1.yes
2.
0线程试图给A加锁
0线程成功给A加锁
0线程试图给B加锁
0线程成功给B加锁
》释放对B的锁
》释放对A的锁,此时A,B都是自由的
1线程试图给B加锁
1线程成功给B加锁
1线程试图给A加锁
1线程成功给A加锁
0线程试图给A加锁
》1线程释放A的锁
》1线程释放B的锁,此时A,B又再次成为自由的
1线程试图给B加锁
0线程成功给A加锁,A被封锁<--
0线程试图给B加锁            |
1线程成功给B加锁,B被封锁<--+-------------------------------------|
1线程试图给A加锁,由于A被线程0锁定,且线程0又在等待B,但是B却被线程1锁定了,所以进入死锁状态。

解决方案 »

  1.   

    Thread.sleep(100);执行后,线程应该失去了对象的锁了,并退出运行状态,转到中间状态了啊(这种中间状态和执行wait()转入相应对象的等待池有什么区别吗?)
      

  2.   

    look this:
    public static void sleep(long&nbsp;millis)
                      throws InterruptedException Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds. THE THREAD DOES NOT LOSE OWNERSHIP OF ANY MONITORS.u can research this by adding print statement before and after sleep(),and set longer time for sleep().and the answer to the last question u said should be same, actually, I think the difference between sleep() and wait() exists just the thread paused by sleep() will wakeup only by timeout, but the one pasued by wait() can be either timeout or notify()so the regular way is putting sleep() out of synchronized statement.
      

  3.   

    哦,THE THREAD DOES NOT LOSE OWNERSHIP OF ANY MONITORS.这么说就基本理解了。  不过我在《Complete Java 2 Certified Study Guide》这本书里好像没有看到这句话哦,呵呵,只是说调用sleep()将使线程从Running转入Sleeping,等时间到了或者调用interrupt(),就转入Ready,然后等系统调度它再进入Running状态。
      结合你的这句话THE THREAD DOES NOT LOSE OWNERSHIP OF ANY MONITORS.,也就是说线程在这整个过程中,始终控制着那个对象的锁喽?是不是这样理解的啊?
      

  4.   

    看看下面这段话,好像和你说的不太一样哦
    Notice that when
    the thread has finished sleeping, IT DOES NOT CONTINUE EXECUTING. As you
    would expect, it enters the Ready state and will only execute when the thread
    scheduler allows it to do so. For this reason, you should expect that a
    sleep() call will block a thread for at least the requested time, but it might
    block for much longer. This suggests that very careful thought should be
    given to your design before you expect any meaning from the nanosecond
    accuracy version of the sleep() method.
      

  5.   

    that paragraph is got from the JDK's document. and the book u mentioned I did not read ever. ur understanding is right i think.the staus of a thread can be one of these:new,runnable(ready u said),running,dead,blocked. a thread be running must be runnable first just as u said above, for there a thread pool and JVM will has it's own arithmetic to pick which runnable thread actually run from the pool. but we can omit this step if we no need care much about the time for make the thread from runnable to running. so there's no confliction between what i said and ur words.
      

  6.   

    照上面所述,我就不明白为什么在
    Thread-0 Looking for lock on Resource A
    Thread-0 Obtained lock on Resource A
    Thread-0 Looking for lock on Resource B
    Thread-0 Obtained lock on Resource B
    Thread-1 Looking for lock on Resource B
    Thread-1 Obtained lock on Resource B
    Thread-1 Looking for lock on Resource A
    Thread-1 Obtained lock on Resource A
    之后会出现
    Thread-0 Looking for lock on Resource A
    Thread-1 Looking for lock on Resource B
    Thread-0 Obtained lock on Resource A
    Thread-0 Looking for lock on Resource B
    Thread-1 Obtained lock on Resource B
    Thread-1 Looking for lock on Resource A
    (死锁中......)
    这样啊?
    既然sleep(),退出了Running状态,也一定是释放了锁了啊,为什么最后会死锁呢?请教请教请教
      

  7.   

    sleep()除了让出执行权外,并不释放任何资源!!!
    这样你理解了吗?
      

  8.   

    这个point我明白了。
    但是我在写这个程序的输出结果的时候,还是没有搞清楚,你来看看我写的output
    注:线程0和1 资源对象A和B >>:寻找 ++:获得  --:释放
    输出结果:
    0>>A
    0++A
    0>>B
    0++B
    0.sleep(100); //在sleep期间,线程0让出执行权,但是不释放B和A.那么线程0在sleep期间,线程1是在干什么呢?是下面这样吗?
    1>>B //这个时候B实际上没有进入运行状态啊,而是处在Seeking Lock State,等到线程0继续执行完,线程0Dead,释放了B和A,那么
    1++B  
    1>>A
    1++A
    1.sleep(100)这么理解的话,变成了o和1轮流来,就不会发生死锁了啊。请问我哪里理解错误了?
     
      

  9.   

    我把sleep的时机改了一下我想有助于你理解。其实以上的代码发生死锁的概率要比下面的代码小一些而以public class Deadlock implements Runnable
    {
      public static void main(String[] args)
      {
        Object a = "Resource A";
        Object b = "Resource B";
        Thread t1 = new Thread(new Deadlock(a, b));
        Thread t2 = new Thread(new Deadlock(b, a));
        t1.start();
        t2.start();
      }  private Object firstResource;
      private Object secondResource;  public Deadlock(Object first, Object second)
      {
        firstResource = first;
        secondResource = second;
      }  public void run()
      {
        for (;;)
        {
          System.out.println(Thread.currentThread().getName()+" Looking for lock on "+firstResource);      synchronized (firstResource)
          {
            System.out.println(Thread.currentThread().getName()+" Obtained lock on "+firstResource);
              try
              {
                Thread.sleep(1000);
              }
              catch (InterruptedException ex) {}
            System.out.println(Thread.currentThread().getName()+" Looking for lock on " + secondResource);
            synchronized (secondResource)
            {
              System.out.println(Thread.currentThread().getName()+" Obtained lock on "+secondResource);
              // simulate some time consuming activity
            }
          }
        }
      }
    }
      

  10.   

    产生死锁的条件是
    t1申请到a锁等待b锁的同时
    t2申请到b锁等待a锁的时产生的
    我在申请锁的间隔中加入sleep,使得另一线程取得另外的资源,造成很容易死锁。
    而原先也需要同样的条件,只不过因为在两处申请资源中间被中断不那么容易
      

  11.   

    请注意sleep的位置,你的情况相当于
    public class Deadlock implements Runnable
    {
      public static void main(String[] args)
      {
        Object a = "Resource A";
        Object b = "Resource B";
        Thread t1 = new Thread(new Deadlock(a, b));
        Thread t2 = new Thread(new Deadlock(b, a));
        t1.start();
        t2.start();
      }  private Object firstResource;
      private Object secondResource;  public Deadlock(Object first, Object second)
      {
        firstResource = first;
        secondResource = second;
      }  public void run()
      {
        for (;;)
        {
          System.out.println(Thread.currentThread().getName()+" Looking for lock on "+firstResource);      synchronized (firstResource)
          {
            System.out.println(Thread.currentThread().getName()+" Obtained lock on "+firstResource);
            System.out.println(Thread.currentThread().getName()+" Looking for lock on " + secondResource);
              try
              {
                Thread.sleep(1000);
              }
              catch (InterruptedException ex) {}
            synchronized (secondResource)
            {
              System.out.println(Thread.currentThread().getName()+" Obtained lock on "+secondResource);
              // simulate some time consuming activity
            }
          }
        }
      }
    }
      

  12.   

    “在两处申请资源中间被中断不那么容易”
    zych72(闹闹)说得对。线程何时被运行是一个不确定的事,依赖与实现者,所以我们写程序时应该深入理解线程模型才能写出线程安全的代码来。
      

  13.   

    因为线程调度的不确定性,在调试线程有时需要通过使用sleep() 来人为的控制线程对系统的控制权