Search

Java - Thread 執行緒的 lock, wait, 與 notify

2015-11-09 6:17 PM

在使用多執行緒我們常常需要使用到 synchronize 確保值的一致性

但是有一些情況很容易造成資料錯亂

這時我們就必須將某一些 Thread lock 住

直到確認其他 Thread 的前置工作完成了 才執行其他 Thread 的後續工作

以下就來介紹執行緒的 lock 該如何設計

本範例將以同一個 class 內的多個執行緒做個簡單示範

程式碼範例
// 宣告一個 final 的變數 將作為參數傳遞至各執行緒
private final Object locker = new Object();

// 宣告另一個變數 作為判斷是否需要 lock 執行緒
// 至於在各執行緒間的傳遞方式有很多種 在這裡就不多作介紹
private boolean commandLock = false;

// Thread 1
while(true){
    if( !isConnected() ){
        lostConnection = true;
        break;
    }

    // 設定為 lock 狀態
    commandLock = true;

    // Do something

    // 設定為 unlock 狀態 並喚醒上一個等待中的Thread
    // 注意此處的 synchronized 是確保同時間只有一個執行緒操作 locker 物件
    commandLock = false;
    synchronized (locker) { locker.notify(); }
}

// Thread 2
public void reloadPage(){
    commandLocker();
    command( "Do reload" );
}

// Locker
private void commandLocker(){
    // 檢查 lock 狀態 若為 lock 狀態則進行 wait 動作
    // 直至 lock 狀態結束
    synchronized (locker) {
        while(commandLock){
            try {
                locker.wait();
            } catch (InterruptedException e) {
                logger.error("Thread sleep error in command locker section.");
            }
        }
    }
}

可能有人會看過在 while loop 中不使用 obj.wait(); 的作法

而是使用 Thread.sleep(millis); 的方式

但此方式容易消耗過多的效能進行不必要的 loop 執行

而且若 millis 沒有設定好 若同時有其他 Thread.sleep(); 的動作

很有因為時間差而可能造成 locker 永遠不會被解除的問題

但若單純使用空的 while 那效能的浪費是非常可怕的

因此還是使用 synchronized 加上 locker 物件的方式會較適當

各項資料連結
Java - Synchronized

No comments:

Post a Comment