線程安全: 當(dāng)多個線程訪問某個類(對象)時(shí)澜汤,不管運(yùn)行時(shí)環(huán)境采用何種調(diào)度方式或者這些線程將如何交替執(zhí)行垒在,并且在主調(diào)代碼中不需要任何額外的同步或者協(xié)同哀峻,這個類都能表現(xiàn)出正確的行為专肪,那么就稱為這個類(對象)是線程安全的呈枉。
線程安全的核心在于要對對象的狀態(tài)訪問操作(read趁尼,write)進(jìn)行管理,特別是對共享的和可變的狀態(tài)的訪問猖辫。
對象的狀態(tài)指的是存儲在狀態(tài)變量(實(shí)例或靜態(tài)域)中的數(shù)據(jù)酥泞。
一個對象是否需要是線程安全的,取決于是否被多個線程訪問住册。要使得對象是線程安全的婶博,需要采用同步機(jī)制來協(xié)同對對象可變狀態(tài)的訪問。
Java中主要的同步機(jī)制有synchronized關(guān)鍵字(獨(dú)占鎖)荧飞,有同步語義的還有volatile變量凡人,顯式鎖以及原子變量。
如果當(dāng)多個線程訪問一個可變狀態(tài)變量并且沒有使用正確的同步機(jī)制叹阔,就會出現(xiàn)錯誤挠轴。有三種方式修復(fù)這個錯誤:
不在線程之間共享該變量狀態(tài)
將狀態(tài)變量修改為不可變的變量
在訪問狀態(tài)變量時(shí)使用同步
在并發(fā)編程中,當(dāng)某個計(jì)算的正確性取決于多個線程執(zhí)行的時(shí)序時(shí)耳幢,就會出現(xiàn)競態(tài)條件(競爭條件)岸晦。比較常見的競態(tài)條件類型就是“先檢查后執(zhí)行(Check-Then-Act)”欧啤,即通過一個可能失效的觀測結(jié)果來決定下一步的行為。
要避免競態(tài)條件启上,就必須在某個縣城修改完可變狀態(tài)后邢隧,通過某種方式防止其他線程使用這個狀態(tài),從而確保其他線程只能在修改完成之前或者之后讀取和修改狀態(tài)冈在,而不是在修改過程中倒慧。
可以將會產(chǎn)生競態(tài)條件的一組操作以加鎖機(jī)制保證這一組以原子的形式執(zhí)行,這一組操作稱為復(fù)合操作包券。
要保持狀態(tài)的一致性纫谅,就需要在單個原子操作中更新所有相關(guān)的狀態(tài)變量。
內(nèi)置鎖
Java的內(nèi)置鎖相當(dāng)于一種互斥鎖
任何一個執(zhí)行同步代碼塊的線程溅固,都不能看到有其他線程正在執(zhí)行由同一個鎖保護(hù)的同步代碼塊
內(nèi)置鎖是可重入的付秕,重入意味著獲取鎖的操作的粒度是縣城而不是調(diào)用(POSIX互斥體的獲取操作是以調(diào)用為粒度的)