不可變物件只要發布了,一定是執行緒安全的。
滿足什麼條件是不可變物件?
如何建立乙個不可變物件?
public static mapunmodifiablemap(map extends k, ? extends v> m)
/*** @serial include
*/private static class unmodifiablemapimplements map, serializable
public int size()
public boolean isempty()
public boolean containskey(object key)
public boolean containsvalue(object val)
public v get(object key)
public v put(k key, v value)
public v remove(object key)
public void putall(map extends k, ? extends v> m)
public void clear()
}
由原始碼可以看出,其講傳入的普通容器物件直接賦給內部維護的不可修改容器類,內部不可修改容器類維護了乙個普通的容器例項,傳入的物件被改內部普通容器變數引用,因此實際上指向的是同乙個物件
如何實現不可修改呢?
從原始碼中也能看出,通過對普通容器方法的包裝,修改操作直接拋異常,查詢操作呼叫內部普通容器物件進行查詢
所有的collections.unmodifiable***類均是這種實現邏輯
下面介紹一下final關鍵字的使用:
執行緒封閉是指變數只能由某個執行緒單獨使用,保證了執行緒安全
執行緒封閉的應用:
資料庫連線對應jdbc的connection物件,connection物件在實現的時候並沒有對執行緒安全做太多的處理,jdbc的規範裡也沒有要求connection物件必須是執行緒安全的。
如何實現執行緒封閉?
通過threadlocal實現
threadlocal介紹
stringbuilder、stringbuffer、arraylist、linkedlist、hashset、hashmap、treeset、treemap均為執行緒不安全的,其內部沒有任何同步措施,不提供任何呼叫的執行緒安全保證
同步容器是指在普通容器的基礎上通過synchronized關鍵字,修飾方法、或者通過指定鎖物件,講所有的併發呼叫該容器的方法,強制序列執行來實現。
其中vector(對應arraylist)、stack、hashtable(對應hashmap,hashmap中允許乙個null鍵,多個null值,但是hashtable中null鍵null值都不允許)分別在方法上修飾synchronized來同步
而collections.synchronized***(list、set、map)如下原始碼所示,通過同一把鎖保持同步,使用方法是傳入乙個普通容器,將其封裝為同步容器,注意由於內部維護的普通容器變數指向傳入的容器物件,因此通過原容器物件可以自由訪問。
public static mapsynchronizedmap(mapm)
private static class synchronizedmapimplements map, serializable
public int size()
}public v get(object key)
}public v put(k key, v value) }}
注意:對同步容器的單次呼叫是執行緒安全的,但是如果在主調**中有組合呼叫操作,比如先檢查後執行、迭代遍歷等,可能會出現不安全,但這並不是同步容器不安全,而是主調**的問題,再此強調所有對同步容器的併發單次操作,是絕對安全的。
同步容器在併發比較低的時候可以使用,其實現簡單,還可以接受。但是在併發量較大時效能很差,因此需要使用併發容器,從名字就可以看出,同步容器會講所有對容器的併發呼叫序列執行,而併發容器能夠實現對容器的併發請求,保持一定的併發執行度。
copyonwritearraylist,其保證執行緒安全的方法是將讀寫分離,讀操作不加鎖在原陣列上讀,寫操作先加鎖然後複製陣列的副本(如下原始碼所示),在副本上修改,因此是滿足最終一致性的,當然這也意味著在修改期間會讀到舊陣列中的資料,是過期的
應用在讀多寫少的場景,因為寫操作需要複製陣列,如果陣列又比較大很浪費時間和記憶體,可能還會導致gc更加造成資源浪費
public e set(int index, e element) else
return oldvalue;
} finally
}
copyonwritearrayset、concurrentskiplistset
concurrenthashmap、concurrentskiplistmap
執行緒限制:乙個被執行緒限制的物件,由執行緒獨佔,並且只能由被占有的執行緒修改
共享唯讀:乙個共享唯讀的物件,只能被執行緒讀取不能被修改,因此併發訪問是安全的
執行緒安全物件:乙個執行緒安全的物件或者容器,在內部通過同步機制(加鎖、cas操作等)來保證執行緒安全,但是這裡的執行緒安全是指單次呼叫該物件的某個方法,如何是組合呼叫並在主調中沒有任何同步,則可能會出現執行緒安全問題
被守護物件:被守護物件只能通過獲取特定的鎖之後,才能訪問
併發程式設計三大特性
1.有序性 當 前後順序發生變化互不影響時,虛擬機會對 進行重排,但是這個操作可能會影響其他執行緒的執行,例子如下 public class test thread t2 new thread new runnable t1.start t2.start t1.join t2.join 等待t1,t...
併發程式設計(三) 開啟程序
上一節說了那麼多關於程序的東西,那這一節就嘗試著自己開啟一下程序 這一節我們可以嘗試著使用multiprocessing模組開啟程序 通過掌握multiprocessing模組開啟程序的兩種方式 是我們在後面的學習的基礎,所以一定要好好看 首先,由於語言特點,python的多執行緒沒辦法使用多核優勢...
併發程式設計系列(三) synchronized內建鎖
synchronized可以對類或者物件加鎖,從而保證多個執行緒在同乙個時刻只有乙個執行緒執行被synchronized修飾的 例子 簡單的購票 現在設計乙個普通的購票場景,乙個票務處,五個客戶同時在票務處買票 1 票務處 ticketmanager 票務處類 classname ticketman...