避免活跃性危险(第十章)
2019獨角獸企業重金招聘Python工程師標準>>>
避免活躍性危險
在安全性與活躍性之間通常存在著某種制衡,我們使用加鎖機制來確保線程安全,但如果過度地使用加鎖,則可能導致“鎖順序死鎖”。同樣,我們使用線程池和信號量來限制對資源的使用,但這些被限制的行為可能會導致資源死鎖。
1. 死鎖
-
鎖順序死鎖:兩個線程試圖以不同的順序來獲得相同的鎖,如果按照相同的順序來請求鎖,那么就不會出現循環的加鎖依賴性,因此也就不會產生死鎖。 在制定鎖的順序時,可以使用System.identityHashCode方法,該方法返回有Object.hashCode返回的值,通過比較大小等方法定義鎖的順序。在某些情況下,兩個對象可能擁有相同的散列值,此時必須通過某種方法來決定鎖的順序,而這可能會重新引入死鎖,為了避免這種情況,可以使用“加時賽”鎖,在獲得兩個對象的鎖之前,首先獲得這個加時賽鎖,從而保證每次只有一個線程以未知的順序獲得這兩個鎖。
-
在協作對象之間發生的死鎖 如果在持有鎖的情況下調用某個外部方法,那么就需要警惕在協作對象之間發生死鎖。 如果在持有鎖時調用某個外部方法,那么將出現活躍性問題,在這個外部方法中可能會獲得其他鎖(這可能會產生死鎖),或者阻塞時間過長,導致其他線程無法及時獲得當前被持有的鎖。
-
開放調用 如果在調用某個方法時不需要持有鎖,那么這種調用被稱為開放調用。 在程序中應盡量使用開放調用。與那些在持有鎖時調用外部方法的程序相比,更易于對依賴于開放調用的程序進行死鎖分析。
-
資源死鎖
2. 死鎖的避免與診斷
3. 其他活躍性危險
引發饑餓的最常見資源就是CPU時鐘周期,如果在Java應用程序中對線程的優先級使用不當,或者在持有鎖時執行一些無法結束的結構(例如無限循環,或者無限制地等待某個資源),那么也可能導致饑餓,因為其他需要這個鎖的線程將無法得到它。線程優先級并不是一種直觀的機制,而通過修改線程優先級所帶來的效果通常也不明顯。當提高某個線程的優先級時,可能不會起到任何作用,或者也可能使得某個線程的調度優先級高于其他線程,從而導致饑餓。
通常,我們盡量不要改變線程的優先級。只要改變了線程的優先級,程序的行為就將與平臺相關,并且會導致發生饑餓問題的風險。Thread.yield以及Thread.sleep的語義都是UB,JVM既可以將他們實現為空操作,也可以將它們視為線程調度的參考。活鎖是另一種形式的活躍性問題,該問題不會導致線程阻塞,但也不能繼續執行。因為線程將不斷重復執行相同的操作,而且總會失敗。 活鎖通常發生在處理事務消息的應用程序中:如果不能成功處理某個消息,那么消息處理機制將回滾整個事務,并將它重新放到隊列的開頭。當多個相互協作的線程都對彼此進行響應從而修改各自的狀態,并使得任何一個線程無法繼續執行時,就發生了活鎖,在并發應用程序中,通過等待隨機長度的時間和回退可以有效避免活鎖的發生。
轉載于:https://my.oschina.net/u/2602561/blog/1560129
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的避免活跃性危险(第十章)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: setAutoCommit(false)
- 下一篇: oracle的本地安装和PUTTY+XM