「Merry,Merry Christmas~Lonely,Lonely Christmas~
想付出不知該給誰,愛我被我們打了死結~」

愛會打死結,那你知道Python也會打死結嗎?!

這篇小知識將告訴你Python內的死結是怎麼來的。

 

資源鎖定與解鎖Threading.Lock

在多執行緒的程式設計中,可能會有多個執行緒皆要存取相同的資源,為了確保執行緒在處理資源期間,可以完成處理不被干擾,此時可以使用Python的鎖定功能Threading.Lock,這個鎖定功能有鎖定與未鎖定2種狀態。在未鎖定狀態可以使用acquire( )方法進入鎖定狀態,此時所鎖定的資源別的執行緒無法存取,當處理資源完成,可以使用release( )方法,將鎖定狀態改為未鎖定狀態。

程式實例ch30_21.py:這個程式會對全域變數進行存取,為了保護順序處理原則,存取前先鎖定全域變數,處理完成後再解鎖。

執行結果

這個程式在Python Shell視窗更可以看出差異。

從上圖可以看到資料符合預期,依序列出。下列實例是,我們不對資料進行鎖

定,各執行緒無法預期誰會先取得資源然後進行資料處理,這種現象稱競速(race condition)。

程式實例ch30_22.py:重新設計ch30_21.py,但是取消第9和12行。

結果顯示出每次執行都會獲得不一樣的結果。

產生死結

在使用Threading.Lock時,如果目前是鎖定狀態(locked),再執行一次acquire( )

這樣會產生死結(dead lock),造成程式錯誤。

程式實例ch30_23.py:程式產生死結(dead lock)測試。

執行結果

由於死鎖產生,所以無法顯示Trying to lock again 字串。

資源鎖定與解鎖Threading.RLock

這是另一種資源鎖定與解鎖,在相同執行緒下這種鎖允許在鎖定狀態時,再度

執行一次acquire( ),差異是acquire( )和release( ) 需要成對出現,如果使用n次

acquire( ),就必須使用n次release( )解鎖。

程式實例ch30_24.py:使用Threading.Rlock 重新設計ch30_23.py,程式不會產生死結(dead lock) 測試。

執行結果