class ThreadA 
{
   public static void main(String[] args) 
   {   
 ThreadB b=new ThreadB();
 b.start();
         System.out.println("b is start....");
         synchronized(b)
     {
       try
       {
        System.out.println("Waiting for b to complete...");   
        b.wait();
        System.out.println("Completed.Now back to main thread");
       }catch (InterruptedException e){}
     }
     System.out.println("Total is :"+b.total);
    }
}class ThreadB extends Thread
{
   int total;
   public void run()
   {
     synchronized(this)
     {
       System.out.println("ThreadB is running..");
       for (int i=0;i<5;i++ )
       {
         total +=i;
         System.out.println("total is "+total);
       }
       notify();
     }
   }
}
===================================================
打印结果是:
b is start....
Waiting for b to complete...
ThreadB is running..
total is 0
total is 1
total is 3
total is 6
total is 10
Completed.Now back to main thread
Total is :10
===============================================
我不太明白这个打印结果的顺序。
为什么在ThreadA中执行b.wait();之后,ThreadB就开始执行了?
以及为什么ThreadA可以进入synchronized(b)得代码块?ThreadA是依据什么来证明自己已经取得b资源了?
还有就是在ThreadA线程中为什么可以执行b.wait();?到底是让谁wait?
谢谢大家!

解决方案 »

  1.   

    synchronized(b){...};的意思是定义一个同步块,使用b作为资源锁。b.wait();的意思是临时释放锁,并阻塞当前线程,好让其他使用同一把锁的线程有机会执行,在这里要用同一把锁的就是b线程本身.这个线程在执行到一定地方后用notify()通知wait的线程,锁已经用完, 待notify()所在的同步块运行完之后,wait所在的线程就可以继续执行
      

  2.   

    其实你这个代码并非完美的,是存在一种可能threadA中的synchronized(b)还未执行时,threadB已经开始的问题,虽然概率不大
    为什么在ThreadA中执行b.wait();之后,ThreadB就开始执行了? //并非如此,b在b.start()后就会开始了,但是由于创建线程需要一定的时间,所以a在大部分的情况下会已经开始执行了后续代码了。
    为什么ThreadA可以进入synchronized(b)得代码块//synchronized(b)的意思是尝试去获取b的锁,如果已经有其它线程获取了它的锁,则一直等待到其它线程释放,直到取得b的锁为止。
    ThreadA线程中为什么可以执行b.wait();?//b.wait的意思并不是让线程b等待,相反是表示让当前的线程也就是a等待,直到有其它线程调用了b.notify/notifyAll为止
      

  3.   

    谢谢!
    为什么ThreadA可以进入synchronized(b)得代码块//synchronized(b)的意思是尝试去获取b的锁,如果已经有其它线程获取了它的锁,则一直等待到其它线程释放,直到取得b的锁为止。
    ==================================
    既然synchronized(b)的意思是尝试去获取b的锁,而ThreadA也进入了synchronized(b)代码块,那么我想知道ThreadA是如何获取到b的锁的?谢谢指教
      

  4.   

    所谓的b的锁你可以看成在b对象身上有一个牌子,synchronized(b)就是向JVM请求获取这个牌子,然后请求的线程身上就多了这一块牌子。至于JVM如何管理这个牌子,如何令请求线程身上多了牌子,则是JVM实现的问题,不同的JVM和不同的操作系统实现方法并不完全一致,多数为使用系统的信号量、互斥体等。
      

  5.   

    谢谢ls!
    那请求synchronized(b)中的b资源和请求者之间不需要有什么关系吗?
    换句话说即使请求者和此资源一点关系也没有也可以申请到加锁资源?
    谢谢指教!
      

  6.   

      
      这段程序是有可能产生死锁的,不过几率小,我在EditPlus里连续运行到几十次后就出现了死锁!
    当synchronized(this) 先于synchronized(b)运行时产生死锁。 b.start(); 
    //code1
    System.out.println( "b   is   start.... "); 
    synchronized(b) 在code1里加上  try
    {
    Thread.sleep(100);
    }
    catch (Exception e)
    {
    e.printStackTrace();
    }
    或者加些其他代码如循环的代码!你会很容易看到结果的!
    synchronized(this) synchronized(b)运行先后是随即的,看谁先得到资源!
      

  7.   

    我主要的疑惑在于:为什么ThreadA线程可以进入要求以拥有b资源为前提的synchronized(b)的代码块?而请求者与资源本是不相关的。换句话说是不是即使请求者与资源不相关,也可以申请到资源?   
    谢谢
      

  8.   

    为什么ThreadA线程可以进入要求以拥有b资源为前提的synchronized(b)的代码块?
    --
    这里是要求拥有b的锁。你可以请求任何对象的锁,不存在限制的。这里不存在所谓的相关与不相关问题,因为在synchronized(b)语句中,你不将因为b是一个线程是另外看待。
    在Java中,synchronized什么对象都是一样的。