多線程的風險漫談

線程的風險java

Java對線程內置支持是一把雙刃劍。它經過提供語言和類庫,以及一個規範的跨平臺存儲模型,簡化了併發應用的開發。這樣作同時提升了開發人員門檻,由於更多的程序須要使用線程,主流的開發人員都必須知道線程安全性的問題。web

併發危險:競爭條件(race condition)。由於線程共享相同的內存地址空間,且併發的運行,它們可能訪問或修改其餘線程正在使用的變量。這其中存在着巨大風險,當數據之外改變時,線程會出現混亂。給順序編程模型引入了一些非順序因素,這可能形成混亂,而且難以發現錯誤的緣由。爲了使多線程程序的行爲可預見,訪問共享變量必須通過合理的協調,這樣線程纔不會相互干擾。Java提供了同步機制來協調這樣的訪問。編程

活躍度的危險:活躍度失敗(liveness failure)。當一個活動進入某種它永遠沒法繼續執行的狀態時,活躍度失敗就發生了。包括死鎖(dead lock)、飢餓(starvation)、活鎖(livelock)。緩存

性能危險: 性能問題包括服務時間、響應性、吞吐量、資源消費或者可伸縮性安全

的不良表現。設計良好的應用使用線程,可以得到純粹的性能收益,可是線程會給運行時帶來必定程序的開銷。上下文切換(Context switches)——當調度程序臨時掛起當前運行的線程時,另外一個線程開始運行——這在多個線程組成的應用程序中是很頻繁的,而且帶來巨大的系統開銷;保存和恢復線程執行的上下文,離開執行的現場,而且CPU的時間會花費在對線程的調度上。當線程共享數據的時候,它們必須使用同步機制,這個機制會限制編譯器的優化,可以清空或鎖定內存和高速緩存,並在共享內存總線上建立同步通訊。這些因素引入了新的性能開銷。微信

 

線程安全多線程

編寫線程安全的代碼,本質上就是管理對狀態(state)的訪問,並且一般都是共享(一個變量能夠被多個線程訪問)、可變(變量的值在其生命週期內能夠改)的狀態。併發

什麼是線程安全性能

當多個線程訪問一個類時,若是不用考慮這些線程在運行時環境下的調度和交替執行,而且不須要額外的的同步及在調用方代碼沒必要做其餘的協調,這個類的行爲仍然是正確的,那麼稱這個類是線程安全的。優化

無狀態的對象永遠是線程安全的。

原子性:假設有操做A和操做B,若是從執行A的線程角度看,當其餘線程執行B時,要麼B所有執行完成,要麼一點都沒有執行,這樣A和B互爲原子操做,一個原子操做是指,該操做對於全部的操做,包括它本身,都知足前面描述的狀態。

鎖:java 提供了強制原子性的內置鎖機制:synchronized塊。它包括兩部分:鎖對象引用,以及這個鎖保護的代碼塊。由於鎖使得線程可以串行地(serialized)訪問它所保護的代碼路徑,因此咱們能夠用鎖建立相關的協議,以保證線程對共享狀態的獨佔訪問。只要始終如一的遵循這些協議,就可以確保狀態的一致性。

本文首發於我的微信公衆號:webguan ;歡迎您的關注

相關文章
相關標籤/搜索