線程安全

線程安全

  • 線程安全定義:線程間共享可變資源(內(nèi)存)。

  • 實現(xiàn)線程安全的方法:

    • 不共享資源。

      使用可重入函數(shù),不對外部資源做任何修改,

    如:public static void plus(int num){return num + 1;}。

    使用ThreadLocal,本質(zhì)上是一個綁定到線程map,故每一個線程都有屬于自己的一份數(shù)據(jù),互不干擾。

    ThreadLocalMapWeakHashMap對比:

    ThreadLocalMap WeakHashMap
    對象持有 弱引用 弱引用
    對象GC 不影響 不影響
    引用移除方式 1. 主動移除。 2. 線程退出時移除 1.主動移除。2.GC后移除
    HASH沖突 開放定址法 單鏈表法(1.8之后加入紅黑樹,保證時間復(fù)雜度降低)
    HASH計算 固定數(shù)值倍數(shù) 對象hashCode再散列
    適用情景 對象少 通用

    使用時注意:

    1. 聲明為全局靜態(tài)final成員。

      ThreadLocal賦值源碼.png

      由源碼可以看出,ThreadLocal賦值時是以自身作為map的key,如果不斷變換ThreadLocal對象的引用,那么設(shè)置進(jìn)去的數(shù)據(jù)就查不出來了。

    2. 避免存儲大量對象。

      由于底層使用開放定址法,數(shù)據(jù)多了容易產(chǎn)生堆積問題。

    3. 用完后及時移除對象。

  • 共享不可變資源。

    訪問被final修飾的數(shù)據(jù)。

  • 共享可變資源,但必須保證:

    1. 可見性,資源的變化對其它線程可見。

      使用volatile修飾,volatile可讓被訪問的數(shù)據(jù)修改時立即對其它線程可見。

      加鎖,鎖施放時會強(qiáng)制將緩存刷新到主內(nèi)存。

    2. 原子性,對資源的操作要么全部執(zhí)行并且執(zhí)行的過程不會被任何因素打斷,要么就都不執(zhí)行 。

      加鎖,保證操作互斥。

      使用CAS指令,如:Unsafe.compareAndSwapInt。

      使用原子數(shù)值類型,如:AtomicInteger

      使用原子屬性更新器,如:AtomicReferenceFieldUpdater。

    3. 禁止重排序。

      使用final、volatile,編譯器會按照自己的規(guī)則重排序編寫的程序,如果由于重排序?qū)е沦Y源在被初始化之前被訪問會增加異常概率。

      final可以保證數(shù)據(jù)都在對象構(gòu)造調(diào)用之前被初始化,volatile可以保證數(shù)據(jù)修改后立即可見。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容