2009-05-06 29 views

回答

6

這是完全正常的。您只能通知在一臺顯示器上等待的所有內容。其他人都不感興趣。您調用notifyAll的對象只是其他人正在等待的顯示器。如果沒有人在等待沒有人需要通知

8

正如您在這裏看到的,在不等待的對象上調用notifyAll()沒有任何影響。

alt text

+0

它可能不是完全正確把一個線程等待對notifyAll的運行,或者至少在沒有需要提醒的是一個通知線程做的第一件事就是regrab監視器鎖定。而且由於通知的線程數量中只有一個可以獲取,所以其他人將被阻止。但阻塞與等待不同,因爲阻塞的線程不需要另一個notify()信號。 – 2012-01-20 15:52:52

1

只有等待對象得到通知。 Object.wait()阻塞,直到超時或通知 - 所以問題仍然是如何或爲什麼你會認爲非等待的對象會得到通知?這個不成立。

+0

對象不會等待或被通知 - 線程可以。在監視器對象上調用notifyAll()而不知道是否有線程在等待它是完全可能的和正常的。例如,在具有隊列的生產者/消費者場景中,當生產者向隊列中添加新元素並通知所有正在等待(即無)消費者時,消費者可能已經清空了隊列並仍然被處理佔用。 – 2009-05-06 08:45:01

+0

我消除了線程以儘可能簡化事情。 – 2009-05-06 10:54:03

2

對象「等待」,不等待自己。線程正在等待。如果沒有人在等待,沒有人會醒來,沒有什麼特別的事情會發生。

+0

當鬧鈴響起但沒人聽到時會發生什麼? – 2012-01-20 15:43:34

2

完全正常的情況。

假設你有一個生產者線程的隊列將元素放入其中,並且一個消費者線程從中刪除元素。

現在消費者可能已經清空了隊列,仍然處於佔用狀態,因此沒有人正在等待隊列變爲非空。現在生產者在隊列中添加一個新元素。如果它正在等待,他必須調用notifyAll()來喚醒消費者。添加額外的邏輯來檢查是否有人正在等待,只有在這種情況下調用notifyAll()纔會增加場景的複雜度(並且非常容易出錯) - 每次只調用notifyAll()會更容易。

1

我可能只會分裂毛髮;-)認爲在notifyAll上從'等待'狀態變爲'運行'狀態的線程可能不是嚴格正確的;至少不是沒有告誡告知線程所做的第一件事就是重新監視監視器鎖定。而且由於通知線程數量中只有一個可以獲取它,其他人將被阻止BLOCKEDThread.State.Blocked)是線程狀態。但阻塞是不等於,因爲阻塞的線程不需要另一個notify()信號來恢復。 [那麼我知道虛假的喚醒,但是對於一些JVM實現來說也許是相反的 - 錯過了通知?]

public class HellBoy { 
    public static class MyThread extends Thread { 
     static final public Object sharedLock = new Object(); 

     public void run() { 
      synchronized (sharedLock) { 
       System.out.println("Gonna wait..."); 
       try { 
        sharedLock.wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       System.out.println("Woken up but sleeping with the lock"); 
       try { 
        Thread.sleep(2500); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       System.out.println("exiting and unlocking"); 
      } 
     } 
    } 

    public static void main(String[] args) throws Exception { 
     new MyThread().start(); 
     new MyThread().start(); 
     new MyThread().start(); 
     new MyThread().start(); 
     Thread.sleep(200); 
     synchronized (MyThread.sharedLock) { 
      MyThread.sharedLock.notifyAll(); 
     } 
    } 
} 
相關問題