2

從使用僅同步方法(沒有鎖或 同步語句)接近於梅薩顯示器,其中 有每個監視器一個條件變量的限度Programming Language Pragmatics, by Scott具有同步方法和同步語句的對象如何分別類似於監視器和條件關鍵區域?

Java對象(並且事實上具有同步語句的對象有時在Java中稱爲 監視器)。

爲什麼僅使用同步方法的Java對象與Mesa監視器非常相似,其中每個監視器有一個條件變量的限制?

「僅使用同步方法的Java對象」中沒有條件變量是否正確?那麼它怎麼能像一個條件變量的監視器?

同樣的道理,Java中的同步語句與等待在一個循環開始 類似於其中的 條件複檢已經作出了明確一個CCR。因爲通知也是明確的,所以在實現關鍵的 部分的每個退出時,Java實現不需要重新評估條件(或者明確地喚醒 線程) - 僅限於發生通知的那些條件。

爲什麼在Java中,與等待在循環開始 synchronized語句酷似CCR(有條件的關鍵區域),其中的條件複檢已經作出了明確?

這是什麼意思?「因爲通知也是顯式的,Java實現不需要在關鍵部分每次退出時重新評估條件(或喚醒顯式執行的線程) - 只有那些發生通知的部分」?

謝謝。

+0

*「爲什麼X像Y'」 *,因爲它們看起來相似,又稱他們在行爲方式相似。如果你瞭解X的行爲,那麼你很快就會明白Y的行爲。你是否理解「Mesa監視器」或「CCR」?如果不是這樣,比較對理解Java監視器沒有幫助,而且任何詳細的逐個功能比較都不會對您有所幫助。如果你理解這些,爲什麼你不認爲它們類似於Java特性? – Andreas

+0

如果您使用關於顯示器的一些常識,您實際上不需要知道Mesa:M​​esa顯示器是顯示器。 – Ben

回答

1

所有這一切都是說,在Java中,內在鎖具有烘焙到它們中的條件。將其與ReentrantLock進行對比,您可以在其中明確地使用相同的鎖定分隔條件。

如果你有單獨的條件,那麼你可以表示一個給定的條件,並知道只有在該條件的等待集中的線程纔會收到它。如果您沒有單獨的條件對象,則在收到通知後,您必須檢查該條件是否適用於您。

一個這樣的例子將是一個固定大小的阻塞隊列。如果您查看ArrayBlockingQueue,它將與ReentrantLock一起實現,以便放置和使用單獨的條件對象。如果這是使用Queue對象上的內部鎖來實現的,那麼它必須使用notifyAll來喚醒等待的線程,然後這些線程必須測試它們從等待中醒來的狀態,以確定它是否與它們相關。

這裏是使用固有鎖寫入的阻塞隊列。如果使用通知,那麼單個線程將被調度程序喚醒,並且(因爲線程可能正在等待放置或等待採取),它可能是也可能不是通知相關的。爲了確保該通知不會丟失所有等待的線程得到通知:

public class Queue<T>{ 

    private final int maxSize; 
    private List<T> list = new ArrayList<>(); 
    public Queue(int maxSize) { 
     this.maxSize = maxSize; 
    } 

    public synchronized T take() throws InterruptedException { 
     while (list.size() == 0) { 
      wait(); 
     } 
     notifyAll(); 
     return list.remove(0)(
    } 

    public synchronized void put(T entry) throws InterruptedException { 
     while (list.size() == maxSize) { 
      wait(); 
     } 
     list.add(entry); 
     notifyAll(); 
    } 
}