1. 程式人生 > >執行緒安全容器

執行緒安全容器

1.同步容器類

同步容器類包括Vector和Hashtable,或者通過Collections.synchronizedXxx等工長方法建立的。

這些實現執行緒安全的方式:將他們的狀態封裝起來,並對每個共有方法加鎖。

1.1 同步容器類的問題

複合操作:迭代(反覆訪問元素,直到遍歷完容器中所有元素)、條件運算(若沒有則新增)。在其他執行緒併發地修改容器時,它們可能會變現出意料之外的行為。

如:

public static Object getLast(Vector list) {
    int lastIndex = list.size() - 1;
    return
list.get(lastIndex); } public static void deleteLast(Vector list) { int lastIndex = list.size() - 1; list.remove(lastIndex); }

當兩個執行緒同時分別執行上面的兩個方法時。會出現問題。如執行緒A呼叫getLast(), 執行緒B呼叫deleteLast(); 呼叫交替執行的圖如下:
這裡寫圖片描述

結構是:getLast將丟擲ArrayIndexOutOfBoundsException異常。

1.2 客戶端加鎖實現同步容器問題

我們解決的思路是通過加鎖來保證Vector的大小在呼叫size和get之間不會發生變化。
如:

public static Object getLast(Vector list) {
    synchronized(list) {
       int lastIndex = list.size() - 1;
       return list.get(lastIndex);
    }
}

public static void deleteLast(Vector list) {
    synchronized(list) {
        int lastIndex = list.size() - 1;
        list.remove(lastIndex);
    }
}

1.3 迭代器與ConcurrentModificationException

同步容器類的迭代器在迭代時,如果被修改時,會變現出“及時失敗”的異常,即ConcurrentModificationException異常。

除了顯示的呼叫迭代會變現出“及時失敗” 的異常外。隱式的呼叫以下方法也有可能出現“及時失敗”,如:hashCode 、equals、containsAll、removeAll和retainAll等方法。

這種“及時失敗”的迭代器並不是一種完備的處理機制,而只是“善意地” 捕獲併發錯誤,因此只能作為併發問題的預警指示器。

解決辦法:

  1. 對容器加鎖
  2. 克隆容器

2. 併發容器

併發容器是從Java 5.0 後引入的。主要的目的是:通過併發容器來代替同步容器,可以極大地提高伸縮性並降低風險。