
238
|
第七章
我們只會鎖住函式中可能會出現爭用情況的部分:讀取帳戶餘額之處、檢查存款是否足
夠之處、更新帳戶餘額之處。一旦程式得知交易是有效的,而且帳戶餘額已更新,它就
可以把鎖釋出,因為錢的支付不具有排他性。關鍵區的範圍愈小愈好,當鎖阻止並行性
時,會因而為執行緒的利益帶來負面的影響。
注意,鎖並無任何神奇之處。要做到完全排他是不可能的。鎖類似一個
君子協定
(
gentlemen
’
s agreement
)。所有執行緒必須在正確的地方取得正確的鎖。要讓執行緒在
必要的時候取得鎖,唯有靠負責任的程式設計。
鎖住資料而非程式碼
在多執行緒程式設計中最重要的一個程式設計模式是
鎖住資料而非程式
碼
(
lock data, not code
)。雖然我們已將討論的範圍限制在關鍵區的爭用
情況,一個好的程式設計者不會把程式碼視為上鎖的對象。你絕不會說:
「這個鎖保護了這個函式。」事實上,一個好的程式設計者會把鎖關聯到
資料。共享資料會有一個相關聯的鎖,要存取該資料總是需要持有相關聯
的鎖。
這有什麼區別嗎?當你把鎖關聯到程式碼,鎖的語義較難以理解。隨著時
間的推進,鎖與資料之間的關係會漸漸變得不清楚,如果沒有適當的鎖,
程式設計者可能會導入資料的新用法。透過把鎖關聯到資料,將有助於保
持映射關係的明確性。
死結
執行緒的殘酷諷刺是:欲望的枷鎖會招致痛苦,這意味著解決方案只會帶來更多的痛
苦。我們想要把執行緒用於並行性,但並行性會帶來爭用情況。所以我們引進了排他
鎖,但是排他鎖會帶來程式設計瑕疵的一個新源頭:死結。
死結
(
deadlock ...