38
1-1 行行 Process 行行行行 Threa d 行行 行行行行行行行行行行行行 行行行行行行行行行行行 行行行行行行行行行行行行行 行 行行行行行行行行行 一。,體,。 行行行行行行 行行行行行行行行 行行行行行行行行行行行行行 行行行行行行行行行 行行行行 行行行行行行 一一。,一, 行行行行行 行行行行行行行行行行 行行 行行行行行行行行行行行 行行行行行行行行行行行行行行 行行行行 ,。一,, 行行行行行行行行 行行行行行行行行行 行 行行行行 行 。,一一 CPU 行行行行行 行行行行行行行行行行行行 行行行 ,, 行行行行行行行行行行行行行行 行行行行行行行行行行 new 行行行行行行行行行 行行行行行行行行行 (ready) 行行行行行行行行行 CPU 行行行行行行行行 行行行行行行行 running 行行行行行行 terminat ed( 行 Zombie) 行行行行行行行行行行行行行行行行行行 System call 行行行行行 行行行行行行行行行 ( 行 preempt) 行行行行行行行行行行行行行 ready 行行行 行行行行行 行行行行行行行行行 / 行行 I/O 行行行行行 (sleep) 行行行 ,, CPU 行行行行 waiting 行行 行行行行行行行 / 行行行行行行行行 ( 行 wake up) 行行行行行 ready 行行行行 行行 ,一 行行行 CPU 行行行行行 行行行行 (zombie 行 terminated)

1-1 行程 Process 與執行緒 Thread 觀念

  • Upload
    zander

  • View
    91

  • Download
    1

Embed Size (px)

DESCRIPTION

1-1 行程 Process 與執行緒 Thread 觀念. 一個行程可以有多個執行緒。執行緒也稱為小的行程,執行緒可以節省更多的記憶體,也比行程更有效能。一個行程就是一個程式正在執行。當我們在終端機下達指令時,作業系統就會建立一個行程,而當我們的程式執行完時,這個行程就被終止了。在一個分時系統的作業系統,允許多個使用者使用電腦系統,而許多行程也同步的被執行。像我們的個人電腦,一般只有一顆 CPU 中央處理器,但卻同時的處理多個行程,而這就分是分時系統。 - PowerPoint PPT Presentation

Citation preview

Page 1: 1-1 行程 Process 與執行緒 Thread 觀念

1-1行程 Process與執行緒 Thread觀念

一個行程可以有多個執行緒。執行緒也稱為小的行程,執行緒可以節省更多的記憶體,也比行程更有效能。一個行程就是一個程式正在執行。當我們在終端機下達指令時,作業系統就會建立一個行程,而當我們的程式執行完時,這個行程就被終止了。在一個分時系統的作業系統,允許多個使用者使用電腦系統,而許多行程也同步的被執行。像我們的個人電腦,一般只有一顆 CPU中央處理器,但卻同時的處理多個行程,而這就分是分時系統。當我們執行程式時,電腦作業系統就會使用 new幫我們產生新的行程,而當我們的行程就緒 (ready)時,而核心又排班分配 CPU中央處理器給他時,他就會開始執行 running,直到執行結束 terminated(或 Zombie)。當然在過程中也有可能發生像系統呼叫的 System call而發生中斷,或者改成其它行程執行 (被 preempt),這時我們的行程就會回到就緒 ready的狀態。當然在過程中也可能發生像輸入 /輸出 I/O或事件等待 (sleep),此時, CPU是在閒置 waiting的狀態,而當我們的輸入 /輸出或事件完成時 (被 wake up),才會到就緒 ready,等待下一次排班分配 CPU中央處理器,直到結束 (zombie或 terminated)。

Page 2: 1-1 行程 Process 與執行緒 Thread 觀念

新產生new

就緒ready

執行running

結束terminated

等待waiting

admitted進入 中斷interrupt exit離開

排班分配scheduler dispatch

/輸入輸出或事件完成I/O or event completion

/輸入輸出或事件等待I/O or event wait

行程狀態圖

Page 3: 1-1 行程 Process 與執行緒 Thread 觀念

• 在分時系統中一個行程在它整個生命期,將在各種不同的排班佇列中,這當然要看我們的需要設計,以及作業系統的設計。因此作業系統需按排班方式從佇列中選出行程,讓所選出的行程讓中央處理器 CPU來執行。而我們所執行的程式也可能只執行一下子,然後就等待輸入 /輸出 I/O的要求,但 I/O的時間,比 CPU所需執行的時間大上很多。在整批作業系統中,大部份的行程都會以 spooling儲存池的方式存到硬碟或大型儲存裝置,等待一個一個的執行。

• 分時系統的中程排班程式是將行程從記憶體中移開,因此而降低多元程式規化的程度,然後再將行程放回記憶體中,並且放在它移開前的位置繼續執行,這種方法稱為 swapping,如下圖所示。

部份已執行置換出來的行程partially excuted swapped-out processes

就緒佇列ready queue

/輸入輸出等代佇列I/O waiting queues

中央處理器CPU

/輸入輸出I/O

加入中程排班的佇列圖

Page 4: 1-1 行程 Process 與執行緒 Thread 觀念

1-1-1執行緒狀態• 執行緒為小的行程,因此行程有的狀態,執行緒都有。這是在 Java中執行緒的狀態。• 當我們使用 new來新增執行緒 new Thread(r),這個執行是還沒有執行,因為它在 ne

w新增的狀態。當一個執行緒在 new的狀態,程式尚未執行程式碼。• 當我們呼叫 start方法,這個程式就是可以準備執行 runnable。一個 runnable可執行的執行緒,它等待作業系統分配 CPU的時間給這個執行緒來 run跑。

• 當一個執行緒在可執行時 runnable,它可能有三個狀態,分別是等待、 timed waiting休息 (或稱為 sleep)和終止 terminated。等待和休息 teimed waiting都是屬於封鎖 block的情況。當執行緒 sleep休息時,它就會到 teimed waiting休息的狀態。當執行緒操作 I/O存取資料時,這時就會在 wait等待,直到 I/O的操作完成後,執行緒才會回到 runnable可執行的狀態。

• 有幾個狀態會讓執行緒由封鎖 block的狀態轉移到 runnable可執行的狀態。當執行緒在休息 tiemed waiting(sleep)時,當休息時間滿了,就會回到 runnable的可執行狀態。當一個執行緒等待 wait一個條件,而其它的執行緒通知 signal給這個執行緒條件已改變,這時這個執行緒就會回到 runnable可執行的狀態。

• 有幾個狀態會讓執行緒由 runnable可執行的狀態轉移到 terminated終止的狀態。當執行緒正常完成工作,它就會到終止 terminated的狀態,然後結束。當例外發生終止 run()函數時,執行緒會突然的終止。

Page 5: 1-1 行程 Process 與執行緒 Thread 觀念
Page 6: 1-1 行程 Process 與執行緒 Thread 觀念

1-2建立執行緒• 這是 Thread類別的函數。我們無法知道執行緒是可執行 runnable還是被封鎖 blocked。我們也無法得知執行緒是runnable正在執行或已經終止了。

Page 7: 1-1 行程 Process 與執行緒 Thread 觀念

• 執行緒類別也有屬性。在 Java程式設計的語言中,每一個執行緒都有優先權priority。我們可以設定執行緒的優先權,使用 setPriority()函數。我們可以設定執行緒的優先權在MIM_PRIORITY(1)到MAX_PRIORITY(10)之間, NORM_PRIORITY預設是 5。當執行緒排程要選取執行緒時,它會先選取高優先權的執行緒來執行。但是執行緒的屬性是由作業系統和硬體所支援。例如Windows XP有七個優先權的層度。一些 Java的優先權將對應到這作業系統。

Page 8: 1-1 行程 Process 與執行緒 Thread 觀念

• Thread類別實作 java.lang.Runable介面。

Page 9: 1-1 行程 Process 與執行緒 Thread 觀念

• 範例: ThreadTest.java• 我們自訂執行緒 PChar類別和 PNum類別和是繼承 java.lang.Thread類別,因此我們的 PChar類別和 PNum類別是自訂的執行緒類別。

Page 10: 1-1 行程 Process 與執行緒 Thread 觀念

• 第二行為我們的main()函數,程式由此開始執行。• 第三行新增自訂執行緒類別 PChar的物件 t,它會列印字元 t, 50次。

• 第四行新增自訂執行緒類別 PChar的物件 r,它會列印字元 r, 50次。

• 第五行新增自訂執行緒類別 PNum的物件 print50,它會列印從 1到50的數字。

• 第六行的 start()函數被呼叫來啟動執行緒 t的 run()函數執行 running。• 第七行的 start()函數被呼叫來啟動執行緒 r的 run()函數執行 running。• 第八行的 start()函數被呼叫來啟動執行緒 print50的 run()函數執行 r

unning。• 第十一行到第二十三行為我們自訂的 PChar類別,它繼承了 Thread類別。

• 第十五行到第十八行為 PChar()的建構子。• 第十九行到第二十三行為 run()函數,它會執行列印字元 t。• 第二十四行到第三十四行為自訂的 PNum類別,它繼承了 Thread類別。

• 第二十六行到第二十八行為 PNum()的建構子。• 第三十行到第三十三行為 run()函數,它會執行列印 1到 n的數字。

Page 11: 1-1 行程 Process 與執行緒 Thread 觀念
Page 12: 1-1 行程 Process 與執行緒 Thread 觀念

• 這個程式有三個獨立的執行緒。因為我們使用執行緒來執行,執行緒它有優先順序。當某個執行緒它執行一段時間後,它的優先權會變低,因此排程就會將CPU的時間分配給較高優先權的執行緒。當執行緒等待一些時間後,它的優先權會變高,高過正在執行 runnable的執行緒時,它就會把 CPU 搶過來 preempt,讓高優先權的轉移到可執行 runnable狀態。因此這三個執行緒搶來搶去的執行。

Page 13: 1-1 行程 Process 與執行緒 Thread 觀念

1-3Thread 群組• Thread 群組就是一群執行緒。有一些程式包含相似功能的少數執行緒,我們可以將它們群組起來。例如我們可以在同一時間暫停或恢復一群 Thread。

• 我們使用 ThreadGroup建構子來建構 Thread 群組。• ThreadGroup tg=new ThreadGroup()• 我們使用 Thread建構子,在 ThreadGroup 群組放置 thread。我們建立一個執行緒,並且將它放置到 thread 群組中。

• Thread t=new Thread(tg,new ThreadClass(),執行緒的標籤 );• 我們使用 activeCount()函數來查詢有多少在群組中的執行緒正在執行。這顯示了在 tg 群組中正在執行的執行緒數量。

• System.out.println(tg.activeCount());• 每一個執行緒都屬於一個執行緒群組。預設,一個新建立的執行緒屬於生產它的執行緒群組。我們使用 getThreadGroup()方法來找尋執行緒群組名稱。

• 我們可以使用在執行緒群組的 start()函數來各別的啟動每一個執行緒。

Page 14: 1-1 行程 Process 與執行緒 Thread 觀念

1-4執行緒的同步和合作• 假如一個可被分享的資源同時的被多個執行緒存取,這個資源可能會發生錯

誤。在作業系統中,因為資源有限,但同時卻有多個行程或應用程式來存取它,這時就會發生搶資源的情況發生,而造成資料結果不一致的情況發生,因此如何讓行程或應用程式有秩序的存取有限資源,這和同步和合作有關。

Page 15: 1-1 行程 Process 與執行緒 Thread 觀念

1-4-1沒有同步存取資源的範例 • 這是一個有限資源,卻由多個執行緒同時存取它,造成資料不一致的情況發生。

• 範例:WithoutSync.java• 假設我們建立和執行 50個執行緒,每一個執行緒都會將一元存入銀行帳號。我們假設一開始存款 balance為 0元,然後再將 1元存入。

Page 16: 1-1 行程 Process 與執行緒 Thread 觀念

• 第二行我們建立 Account 帳號類別物件 account。,• 第三行我們建立執行緒陣列,並放入 50個執行緒。• 第四行到第九行為main()函數,它會執行兩遍存款 50次執行緒的動作。• 第五行新增WithoutSync類別的物件 test。• 第六行使用 test.account.getBalance()來得到銀行存款帳戶的金額。• 第七行再新增WithoutSync類別的物件 test1。• 第六行再使用 test1.account.getBalance()來得到銀行存款帳戶的金額。• 第十行到第二十行為WithoutSync類別的建構子。• 第十一行新增 ThreadGroup執行緒群組類別物件 g。• 第十四行新增執行緒,並將它放到 thread[i] 陣列中。• 第十五行使用 thread[i].start()來啟動第 i個執行緒。• 第二十一行到第二十五行為 AddAPennyThread執行緒類別,它繼承了 Thread執行緒類別。

• 第二十二行到第二十四行為 AddApennyThread執行緒類別的 run()函數,它會存 1元到銀行帳戶中。

• 第二十六行到第四十三行是建立帳號 Account類別。• 第二十九行到第三十一行定義 getBalance()函數,他們會回傳 balance 帳戶的存款金

額。• 第三十三行到第四十二行的 deposit()存款函數,帶入整數 amount的存款。• 第三十六行的 Thread.sleep(1)會讓執行緒休息百萬分之一秒,這時期它的執行緒就有可能執行,而產生資料不一致的情況,因此將第三十五行到第三十九行去掉,則不一致的情況就不會發生了。因為執行緒互相在搶存入 balance的資源。

• 第三十四行將銀行的帳戶金額 balance 加上存款 amount。• 第三十四行到第四十一行稱為 critical region 關鍵區域。• 第十八行的 g.activeCount()是會得到目前執行緒群組還存活的數量,當所有執行緒都執行完,它就會回傳 true,就會跳出 while 迴圈。

Page 17: 1-1 行程 Process 與執行緒 Thread 觀念
Page 18: 1-1 行程 Process 與執行緒 Thread 觀念

• 兩次銀行帳戶的存款一開始都為 0,執行完 50個執行緒後,應該有 50元,但是兩次結果都不是 50元,因此這個結果是不可預定的。當所有執行緒同時存取 deposite()函數時,這個資料就會發生錯誤不一致。

• 將第三十五行到第三十九行拿掉,因為這是會讓程式錯誤發生的情況。

Page 19: 1-1 行程 Process 與執行緒 Thread 觀念

• 因為執行程式沒有一次執行完,中間又休息,這時又有另外一個程式在執行存取相同的資料,這時就會發生資源存取不一致的情況發生。 Thread[i]執行緒 i在執行讓 newBalacne的值為 1。在時間 2,執行緒 [i]先休息 sleep,這時後還沒將 1的資料存入到 balance中。 Thread[j]執行緒 j這時後在時間2的地方開始執行,這時取到 balance的資料為 0,因此 0+1為 1, newBalance的資料為 1,然後再休息 1的時間。在時間 3, Thread[i]將 newBalance的資料 1給 balance。在時間 3Thread[j]為休息。在時間 4, Thread[j]將newBalance的資料 1給 balance,這時 balance 銀行帳戶存款的結果為 1。

• 兩個執行緒搶資源執行的結果,造成資料存取不一致的現象而發生錯誤。

執行時間 balance thread[i] thread[j]

1

2

3

0

0

1

1

newBalance=balance+1

sleep(1)

balance=newBalance

newBalance=balance+1

balance=newBalance

sleep(1)

4

Page 20: 1-1 行程 Process 與執行緒 Thread 觀念

1-4-2同步的範例• 我們在這裏為了讓程式能夠一次由一個執行緒執行完,讓資料能夠一致性的存取,我們使用 lock鎖的觀念。 Lock鎖就是將關鍵區域 critical region鎖住的程式區塊,一次只允許一個執行緒來存取,直到 unlock 解開鎖為止。這樣可以保證資料存取一致的情況。

• JDK5.0使用 ReentrantLock類別,它為 lock鎖的類別。它是在 java.util.concurrent.locks.ReentrantLock 套件類別。 ReentrantLock()為它的建構子,它可以用來保護關鍵區域 critical region。 ReentrantLock類別中的 lock()方法是取得鎖, unlock()方法是釋放鎖。

• 範例: Sync.java• 第一行我們輸入 java.util.concurrent.*。• 第二行我們輸入鎖的套件 java.util.concurrent.locks.*。• 第三十行我們新增一個 ReentrantLock() 靜態物件的鎖 lock。• 第三十六行到第四十五行我們使用鎖 lock來鎖住關鍵區域 critical region。• 第三十六行使用 lock.lock()來鎖住。• 第四十四行使用 lock.unlock()來解開鎖。

Page 21: 1-1 行程 Process 與執行緒 Thread 觀念
Page 22: 1-1 行程 Process 與執行緒 Thread 觀念

這是執行的情況。

Page 23: 1-1 行程 Process 與執行緒 Thread 觀念

1-4-3Syncronized同步化關鍵字• 我們也可以使用 syncronized 關鍵字來保護資料,它可以保證資料被同步存取。

• public synchronized void deposit(int amount)。一個 synchronized同步化的函數在執行前會需要一個鎖。在這實體函數的範例,當函數被呼叫時,一個鎖 lock就會被啟動。在這靜態函數的範例中,鎖是在類別上。假如執行緒呼叫一個在物件上 synchronized同步化的實體函數,這物件的鎖就會被獲得,當函數執行完後,這物件的鎖就會被釋放。其它執行緒在這段期間呼叫這個物件 synchronized同步化的方法,將被檔住,直到這個函數執行完,鎖被釋放 unlocked為止。

Page 24: 1-1 行程 Process 與執行緒 Thread 觀念

• 我們在 deposit()函數前加上 synchronized 關鍵字。• 範例:WithoutSync3.java

• 假如我們無法修改 deposit()函數,我們可以新增一個 synchronized同步的方法來呼叫 deposit()函數。

• 語法:• synchronized(expr){• statement ;• }• 這個 expr 運算式一定要是物件的

參考。假如這個物件已經被其它執行緒鎖住 locked,其它執行緒在鎖解開前是不可以存取這個物件的。synchronized同步化敘述讓我們獲得鎖用在物件上,所以我們可以同步存取物件,而不是只有在方法上。

Page 25: 1-1 行程 Process 與執行緒 Thread 觀念

• 範例:WithoutSync5.java• 第二十五行到第二十七行使用 synchron

ized()函數來同步化物件 account,我們將鎖加入到該物件,直到第二十六行的敘述執行完才解開鎖。

Page 26: 1-1 行程 Process 與執行緒 Thread 觀念

1-4-4執行緒的合作• 執行緒同步化是未了避免資源競爭的情況發生,我們可以讓關鍵區域 critical r

egion的多個執行緒能夠互斥 mutual來達成,但有時後執行緒間還是要合作。wait()、 notify()和 notifyAll()函數可以用來幫助執行緒間作溝通。 wait()函數會讓執行緒等待 wait,直到某個條件發生。當它發生時,我們可以使用 notify()函數或者是 notifyAll()函數來通知這 waiting等待的執行緒來恢復一般的執行。 notifyAll()函數叫醒所有 waiting等待的執行緒,而 notify() 則從等待的佇列叫醒一個執行緒。

• wait()、 notify()和 notifyAll()函數必需被在一個同步 synchronized的函數或同步 synchronized的區塊內呼叫,並且在這些函數的接收物件上,否則 IllegalMonitorStateException例外將會發生。

• 在執行緒 1時,當 condition條件為假時,它會執行 while 迴圈,執行 anObject.wait()函數,等待人來解救它,它會一直等待 wait,直到執行緒 2執行 synchronized()同步函數,並且在裏面使用 anObject 物件的 notify()函數來叫醒它。這時後執行緒 1又再會繼續執行 while 迴圈。

synchronized(anObject){ while(!condition){

anObject.wait(); }

}

Thread1 1執行緒

synchronized(anObject){ anObject.notify();

}

Thread2 2執行緒

恢復

Page 27: 1-1 行程 Process 與執行緒 Thread 觀念

• 一個同步的鎖 lock 必需被在 wait等待或 notify通知的物件上獲得。當 wait()函數被呼叫時,它暫停這個執行緒,而且同步的釋放在物件上的鎖 lock。當這執行緒被通知 notify而啟動時,這鎖將自動的被獲得。

• 範例: Cooperation.java• 這是銀行存款執行緒 1和銀行提款執行緒 2,但是銀行的帳戶永遠的金額都大於 0。這是典型銀行存款的執行緒合作。

• 第二行我們新增 Account類別的物件 account。• 第三行新增存款執行緒 DepositThread類別的物件 t1。• 第四行新增提款執行緒WithdrawThread類別的物件 t2。• 第五行到第八行是main()函數,程式執行的地方。• 第六行會新增 Cooperation類別的物件 test,這時後 Cooperation開始執行。• 第九行到第十二行是 Cooperation的建構子。它讓執行緒 1和執行緒 2開始執行。

• 第十三行到第二十五行是定義存款執行緒。• 第十四行到第二十四行是 run()函數,當執行緒 1.start()被呼叫時它就會被執行。

• 第十六行是呼叫 account.deposit()來作存款的動作。• 第十八行 Thread.sleep(100)是讓存款執行緒休息百萬分之 100 秒,這時就

換提款執行緒WithdrawThread會執行。• 第二十六行到第三十二行是定義 WithdrawThread 提款執行緒。• 第二十九行 account.withdraw()會作提款的動作,也就是將銀行的帳戶金額作減少。

Page 28: 1-1 行程 Process 與執行緒 Thread 觀念

• 第三十三行到第五十四行是定義 Account 銀行帳戶類別。• 第三十四行定義 balance為銀行帳戶存款金額。• 第三十五行到第三十七行會回傳銀行帳戶存款金額。• 第三十八行到第四十二行定義同步化 synchronized的存款 deposit()函數。• 第三十九行 balance+=amount是存款 amount 金額到 balance 帳戶。• 第四十一行使用 this.notify()來告知這個物件,讓在 wait()的物件醒來。• 第四十三行到第五十三行定義同步化 synchronized的提款 withdraw()函數。• 第四十五行到第四十六行為 while 迴圈,當存款金額小於 0時,就會執行這個迴圈,然後 wait。當存款後 (執行存款執行緒 DepositThread),它會執行第十六行的存款,然後執行第四十一行的 notify()函數來告知 account 物件的wait()函數醒來,再執行第四十五行 while 迴圈。

• 第五十一行 balance=balance-amount是將銀行帳戶的 balance 減去 amount金額,也就是從帳戶提款 amount。

• 第四十一行使用 this.notify()來告知這個物件,讓在 wait()的物件醒來。

Page 29: 1-1 行程 Process 與執行緒 Thread 觀念
Page 30: 1-1 行程 Process 與執行緒 Thread 觀念
Page 31: 1-1 行程 Process 與執行緒 Thread 觀念

• 當銀行帳戶的金額小於提款時,這時後就會到 wait等待的狀態,直到執行緒 1,將存款存入 notify(),而銀行帳戶的存款不小於 0時才會顯示銀行帳戶的金額,因此看到的銀行帳戶金額都不小於 0。

• 死結 deadlock的發生,當一個正在 waiting的執行緒不能再動時,因為執行緒 1在等待執行緒 2來處理,但是執行緒 2也同時不能再動,因為執行緒 2等待執行緒 1來處理。兩個執行緒互相等待對方,所以死結就發生了,兩個都不會動了。

Page 32: 1-1 行程 Process 與執行緒 Thread 觀念

1-5執行緒範例實作• 在 SynchTest類別中,我們將銀行 Ban

k類別帳戶的錢作移動 TransferRun,當某個帳戶的金額小於要移動的 amount 金額,這時它就會等待,等到其它帳戶將金錢移動到它帳戶時,而且這個帳戶的金額大於移動的金額 amount時,這個帳戶的執行緒就會開始執行移動的動作。這是 UML的圖。 SynchTest為我們的主程式類別。

• TransferRun移動金錢類別實作 Runnable介面。 Thread執行緒是由 TransferRun 物件所組成, Thread類別會啟動TransferRun實體的 run()函數。 SynchTest類別則由 Thread和 Bank實體所組成。

Page 33: 1-1 行程 Process 與執行緒 Thread 觀念

• 範例: SynchTest.java• 第一行輸入 java.util.concurrent.locks.*  套件的所有類別。• 第十行到第十五行為 for 迴圈,它會執行十次迴圈。• 第十二行新增 TransferRun類別物件 r。• 第十三行新增執行緒類別物件 r,並且將 r 物件 (runnable) 帶入建構子中。

• 第十四行使用 t.start()來啟動執行緒。• 第七十二行到第九十九行為 TransferRun類別,它會實作 runnable介面,它會完成 run()函數。它是將銀行帳戶的錢從 fromAccount移動到 toAccount 帳戶,使用move()函數。

• 第十八行到第七十行為 Bank類別。• 第二十三行到第三十行為 Bank類別的建構子。• 第二十八行新增 ReentrantLock鎖類別物件為 bankLock。• 第二十九行使用 ReenttrantLock鎖類別的方法 newCondition()來新增 Condition類別物件 sufficientFunds。 Condition條件類別的物件sufficientFunds可以和 Lock實體一起用。

• 第三十一行到第四十九定義 move()函數,它會丟出 InterruptedException中斷例外,它是將 from 帳號的 amount 金額移動到 to 帳號去。

• 第三十三行使用 bankLock.lock()的鎖。

Page 34: 1-1 行程 Process 與執行緒 Thread 觀念

• 第三十六行到第三十七行為 while 迴圈,當 from 帳號的金額小於 amount移動的金額時,它就會等待,直到其它執行緒執行move()將錢移動到這個帳戶,然後在 signalAll()通知它 sufficientFunds,這時後才會再執行第三十六行的while 迴圈來判別是否 from的金額大於移動 amount的金額,如果是則到第三十八行。

• 第三十八行會顯示目前執行緒的名稱 Tread.currentThread()。• 第三十八行到第四十二行為關鍵區域 critical region,它會將 from 帳號的錢 a

mount移動到 to 帳號去,也就是作一加一減的動作。• 第四十三行是通知 signal所有 sufficientFunds條件鎖物件。• 第四十七行最後解開鎖。• 第五十行到第六十六行為 getTotalBalance,它會將陣列 accounts的所有元

素值,也就是將所有帳號的金額加起來,這就是帳號總金額,然後回傳。• 第五十二行到第六十四行為關鍵區域,所以使用鎖 bankLock來將它鎖住。• 第七十二行為 TransferRun類別,它實作了 Runnable介面。• 第七十八行我們定義 DELAY為 0.1 秒。在 Java中百萬分之一秒為單位。• 第七十九行到第八十四行為定義 TransferRun建構子。• 第八十五行到第九十八行為實作 Runnable介面的 run()函數。• 每一個執行緒物件都有 TransferRun類別的物件,它會執行 run()函數。• 第九十三行為移動帳戶間的移動金錢 move()。• 第九十四行為執行緒休息 sleep()。

Page 35: 1-1 行程 Process 與執行緒 Thread 觀念
Page 36: 1-1 行程 Process 與執行緒 Thread 觀念
Page 37: 1-1 行程 Process 與執行緒 Thread 觀念
Page 38: 1-1 行程 Process 與執行緒 Thread 觀念

• 這是帳戶間移動金錢的情況。