【併發編程】線程安全策略

線程封閉

線程封閉

把對象封裝到一個線程裏,只有這個線程能看到這個對象。html

實現線程封閉

Ad-hoc 線程封閉:程序控制實現,最糟糕,忽略
堆棧封閉:局部變量,無併發問題
ThreadLocal 線程封閉:特別好的封閉方法java

ThreadLocal 實例保存登陸用戶信息編程

public class RequestHolder {
    private final static ThreadLocal<Long> requestHolder = new ThreadLocal<>();

    /**
     * 添加數據
     * 在filter裏將登陸用戶信息存入ThreadLocal
     * 若是不使用ThreadLocal,咱們會須要將request一直透傳
     * @param id
     */
    public static void add(Long id){
        // ThreadLocal 內部維護一個map,key爲當前線程名,value爲當前set的變量
        requestHolder.set(id);
    }

    /**
     * 獲取數據
     * @return
     */
    public static Long getId(){
        return requestHolder.get();
    }

    /**
     * 移除變量信息
     * 若是不移除,那麼變量不會釋放掉,會形成內存泄漏
     * 在接口處理完之後進行處理(interceptor)
     */
    public static void remove(){
        requestHolder.remove();
    }
}

線程不安全的類與寫法

1.StringBuilder 線程不安全,StringBuffer線程安全
緣由:StringBuffer幾乎全部的方法都加了synchronized關鍵字。安全

2.SimpleDateFormat
SimpleDateFormat 在多線程共享使用的時候回拋出轉換異常,應該才用堆棧封閉在每次調用方法的時候在方法裏建立一個SimpleDateFormat。
另外一種方式是使用joda-time的DateTimeFormatter(推薦使用)。多線程

3.ArrayList,HashMap,HashSet等Collections併發

4.先檢查再執行高併發

// 非原子性
if(condition(a)){
  handle(a);
}

同步容器

如今使用的比較少,主要使用併發容器。
ArrayList->Vector,Stack
HashMap->HashTable工具

Collections.synchronizedXXX (list,set,map)ui

併發容器

J.U.C下的工具類:【併發編程】【JDK源碼】JDK的(J.U.C)java.util.concurrent包結構線程

ArrayList->CopyOnWriteArrayList
HashSet/TreeSet->CopyOnWriteArraySet/ConcurrentSkipListSet
HashMap/TreeMap->ConcurrentHashMap/ConcurrentSkipListMap

安全共享對象策略

安全地共享對象包括如下幾種策略:

線程限制:一個被線程限制的對象,由線程獨佔,而且只能被佔有它的線程修改。
共享只讀:一個共享只讀的對象,在沒有額外同步的狀況下,能夠被多個線程併發訪問,可是任何線程都不能修改它。
線程安全對象:一個線程安全的對象或者容器,在內部經過同步機制來保證線程安全,因此其餘線程無需額外的同步就能夠經過公共接口隨意訪問它。
被守護對象:被守護對象只能經過獲取特定的鎖來訪問。

參考資料:
慕課網高併發實戰(六)- 線程安全策略

相關文章
相關標籤/搜索