鎖定

系統中可能會有多重工作需要存取和操作相同的物件。ILock 定義授予獨佔性存取共用物件的協定。當工作需要共用物件的存取權時,它會取得該物件的鎖定。當完成操作物件時,會解除鎖定。

通常是在建立或外掛程式第一次存取共用物件時建立鎖定。也就是說,參照共用物件的程式碼也會參照它的鎖定。我們將從建立鎖定 myLock 開始,將會用來控制 myObject 的存取權:

   ...
   myObject = initializeImportantObject();
   IJobManager jobMan = Platform.getJobManager();
   myLock = jobMan.newLock();
   ...

平台提供 ILock 的強韌實作。工作管理程式提供這個鎖定的實例供用戶端使用。這些鎖定彼此互相知道且可以避免循環死結。(我們稍後會更深入解釋這個陳述。)

每當工作中的程式碼需要存取 myObject,必須先取得它的鎖定。下列片段顯示使用鎖定的一般用法:

...
// 我必須操作 myObject,因此我需要先取得其鎖定。
try {		
	myLock.acquire();
	updateState(myObject);  // 操作物件
} finally {
	lock.release();
}
...

在授予鎖定的獨佔性存取權給呼叫工作之前,acquire() 方法將不會傳回。換句話說,如果有些其他工作已經取得鎖定,則會鎖定這些程式碼,直到能夠取得鎖定為止。請注意,取得鎖定和操作 myObject 的程式碼是包圍在 try 區塊中,如果在使用物件時發生任何異常狀況即可釋放鎖定。

看起來很簡單,對吧?很幸運地,鎖定的使用方式十分直接。它們也是可重複進入的,表示您不需要擔心您的工作會多次取得相同的鎖定。每一個鎖定會保存特定執行緒的取得和釋放數目,而且只能在釋放數等於取得數時從工作中釋放。

死結

之前,我們提到工作管理程式提供的鎖定彼此會互相知道,而且可以避免循環死結。如果要瞭解死結如何發生,讓我們看一個簡單的實務。假設「工作 A」取得「鎖定 A」,接著嘗試取得「鎖定 B」。這時,「工作 B」握有「鎖定 B」,這個鎖定正在等待「鎖定 A」。這種死結指出工作間使用鎖定的基礎設計問題。這個簡單的狀況很容易可以避免,當您的設計中使用的工作和鎖定數增加時,意外發生死結的機會也隨著增高。

很幸運地,平台將會幫助您識別死結。當工作管理程式偵測道死結狀況時,會列印診斷資訊到日誌中來說明死結狀況。然後,暫停執行的工作所擁有的鎖定會暫時授予存取權給其他等待工作。仔細測試牽涉到多重鎖定的實作並修正平台報告的任何死結狀況是非常重要的。