code

2017年8月4日 星期五

Concurrent Java 1 - Structured / Intrinsic Lock / Monitors

Structured Lock (intrinsic lock / monitors)

這就是synchronized keyword,特徵就是thread mutual exclusion是implicit達成,沒有任何一個explicit lock出現。

每個Java object都有一個intrinsic lock,一個thread要對此object獲得mutual exclusive right的話,就要acquire這個object的intrinsic lock:

thread X: acquire A's lock ----- (own the lock) ------> release A's lock
thread Y: --------------block when try to acquire A's lock-------acquire A's lock ..........


一個thead 如何acquire object A's intrinsic lock?

1. 呼叫A的synchronized instance method會自動獲得A's lock,在method returns/throws exceptions 會自動release lock。如果是synchronized class method,則獲得此class的關聯Class object的instrinsic lock,保護static fields。

2. 使用 synchronized(A),這可以放在比較fine-grained小區域保護範圍。


Reentrant Synchronization

Java lock可以被同一個thread acquire多次,這保護這個thread不會自己把自己block住了,所以不用害怕會發生這樣的事。不過既然稱為structured lock,則acquire lock的順序會配合上相反順序的release。


Wait / Notify

假設以下的程式在等待一個flag joy被設為true:

public void guardedJoy() {
    // Simple loop guard. Wastes
    // processor time. Don't do this!
    while(!joy) {}
    System.out.println("Joy has been achieved!");
}

某個thread要是執行這個method,就會在while loop裡面一直等待,但是OS還是會分配CPU resource來執行這個while loop,等於浪費CPU資源。如果把此method加上synchronized keyword,此時可以呼叫此object instance 的wait()來suspend這個thread:

public synchronized void guardedJoy() {
    // This guard only loops once for each special event, which may not
    // be the event we're waiting for.
    while(!joy) {
        try {
            wait(); //the thread releases the lock and is suspended
        } catch (InterruptedException e) {}
    }
    System.out.println("Joy and efficiency have been achieved!");
}


此thread被suspended,只有當某個Interrupt發生才會resume,例如其他的thread呼叫notifyAll,但是這不一定是我們在等待的interrupt (e.g. 不一定是joy被改變的事件),所以一定要在檢查condition的loop中呼叫wait(),才能在interrupt發生的時候檢查condition來決定是否繼續wait。

為什麼要把此method加上synchronized? 其實是因為要呼叫此object的wait() method必須要acquire 此object's intrinsic lock。

一旦呼叫wait(),則thread會release此object lock然後suspended。

某個method會讓另一個thread acquire lock並且產生interrupt來notify所有suspended threads:

public synchronized notifyJoy() {
    joy = true;
    notifyAll();
}

被interrupt甦醒的thread 會重新獲得這個object's lock (因為另一個thread在method returns就release lock),繼續在while loop中檢查是否要繼續wait。







沒有留言:

張貼留言