「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) 測試。