同步方法 - 这是如何工作的?

时间:2013-04-26 19:47:00

标签: java thread-safety synchronized

我最近看到了一个例子。我无法理解主线程和乘客线程如何一次保持在同步块中?

public class bus 
{
    public static void main(String[] args) throws InterruptedException 
    {
        passenger p = new passenger();
        p.start();
        synchronized (p) 
        {
            System.out.println("passenger is waiting for the bus, i am in synchronised method");
            p.wait();
            System.out.println("passenger  got notification");
        }
        System.out.println("after "+p.total+" time");
    }
}

class passenger  extends Thread 
{
    int total = 0;

    public void run() 
    {
        synchronized (this) 
        { 
            System.out.println("wait ....  i am in synchronised method");
            for (int i = 0; i <= 1000; i++)
            total = total + i;
            System.out.println("passenger  is given  notification call");
            notify();
        }
    }
} 

该程序的输出是

passenger is waiting for the bus i am in synchronised method
wait ....  i am in synchronised method
passenger  is given  notification call
passenger  got notification
after 500500 time

这意味着当主线程打印“乘客正在等待总线时我处于同步方法”时,它已经处于同步块并等待。打印的下一个语句是“等待......我在同步方法中”,这意味着乘客线程也进入了同步块。请记住,两个同步块都具有相同的对象 - p作为块对象。这似乎令人困惑,因为我理解当主线程输入synchronized(p)块时,主线程必须阻止对象p,并且根据定义,没有其他线程可以访问或输入任何同步的块或对象方法{{ 1}}!

1 个答案:

答案 0 :(得分:4)

  

主线程和乘客线程如何一次保持在同步块中?

p.wait() 发布锁定p,直到线程重新唤醒,因此synchronized上任意数量的线程都可以ppublic final void wait() throws InterruptedException 只要最多一个人不等待。

来自Object's javadoc

notify
     

当前线程必须拥有此对象的监视器。 线程释放此监视器的所有权并等待,直到另一个线程通过调用notifyAll方法或{{1}}方法通知等待此对象监视器的线程唤醒。然后该线程等待,直到它可以重新获得监视器的所有权并继续执行。