Search

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

2015-11-09 6:17 PM

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

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

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

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

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

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

程式碼範例
  1. // 宣告一個 final 的變數 將作為參數傳遞至各執行緒
  2. private final Object locker = new Object();
  3.  
  4. // 宣告另一個變數 作為判斷是否需要 lock 執行緒
  5. // 至於在各執行緒間的傳遞方式有很多種 在這裡就不多作介紹
  6. private boolean commandLock = false;
  7.  
  8. // Thread 1
  9. while(true){
  10. if( !isConnected() ){
  11. lostConnection = true;
  12. break;
  13. }
  14.  
  15. // 設定為 lock 狀態
  16. commandLock = true;
  17.  
  18. // Do something
  19.  
  20. // 設定為 unlock 狀態 並喚醒上一個等待中的Thread
  21. // 注意此處的 synchronized 是確保同時間只有一個執行緒操作 locker 物件
  22. commandLock = false;
  23. synchronized (locker) { locker.notify(); }
  24. }
  25.  
  26. // Thread 2
  27. public void reloadPage(){
  28. commandLocker();
  29. command( "Do reload" );
  30. }
  31.  
  32. // Locker
  33. private void commandLocker(){
  34. // 檢查 lock 狀態 若為 lock 狀態則進行 wait 動作
  35. // 直至 lock 狀態結束
  36. synchronized (locker) {
  37. while(commandLock){
  38. try {
  39. locker.wait();
  40. } catch (InterruptedException e) {
  41. logger.error("Thread sleep error in command locker section.");
  42. }
  43. }
  44. }
  45. }

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

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

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

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

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

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

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

各項資料連結
Java - Synchronized

No comments:

Post a Comment