線程安全
線程安全定義:線程間共享可變資源(內(nèi)存)。
-
實現(xiàn)線程安全的方法:
-
不共享資源。
使用可重入函數(shù),不對外部資源做任何修改,
如:
public static void plus(int num){return num + 1;}。使用
ThreadLocal,本質(zhì)上是一個綁定到線程map,故每一個線程都有屬于自己的一份數(shù)據(jù),互不干擾。ThreadLocalMap與WeakHashMap對比:ThreadLocalMap WeakHashMap 對象持有 弱引用 弱引用 對象GC 不影響 不影響 引用移除方式 1. 主動移除。 2. 線程退出時移除 1.主動移除。2.GC后移除 HASH沖突 開放定址法 單鏈表法(1.8之后加入紅黑樹,保證時間復(fù)雜度降低) HASH計算 固定數(shù)值倍數(shù) 對象hashCode再散列 適用情景 對象少 通用 使用時注意:
-
聲明為全局靜態(tài)final成員。
ThreadLocal賦值源碼.png由源碼可以看出,
ThreadLocal賦值時是以自身作為map的key,如果不斷變換ThreadLocal對象的引用,那么設(shè)置進(jìn)去的數(shù)據(jù)就查不出來了。 -
避免存儲大量對象。
由于底層使用開放定址法,數(shù)據(jù)多了容易產(chǎn)生堆積問題。
用完后及時移除對象。
-
-
共享不可變資源。
訪問被final修飾的數(shù)據(jù)。
-
共享可變資源,但必須保證:
-
可見性,資源的變化對其它線程可見。
使用volatile修飾,volatile可讓被訪問的數(shù)據(jù)修改時立即對其它線程可見。
加鎖,鎖施放時會強(qiáng)制將緩存刷新到主內(nèi)存。
-
原子性,對資源的操作要么全部執(zhí)行并且執(zhí)行的過程不會被任何因素打斷,要么就都不執(zhí)行 。
加鎖,保證操作互斥。
使用CAS指令,如:
Unsafe.compareAndSwapInt。使用原子數(shù)值類型,如:
AtomicInteger。使用原子屬性更新器,如:
AtomicReferenceFieldUpdater。 -
禁止重排序。
使用final、volatile,編譯器會按照自己的規(guī)則重排序編寫的程序,如果由于重排序?qū)е沦Y源在被初始化之前被訪問會增加異常概率。
final可以保證數(shù)據(jù)都在對象構(gòu)造調(diào)用之前被初始化,volatile可以保證數(shù)據(jù)修改后立即可見。
-
