序列資料結構在併發環境下是不安全的,而直接使用鎖又會帶來效能的影響,所以jdk專門設計了針對併發環境下的資料結構,其中使用了無鎖運算來保證效能。
1.可以直接使用collections.synchronizedlist()將乙個非執行緒安全的list變成支援同步的list.但是這樣做有乙個問題,就是所有的操作都會被加上鎖,我們知道如果只有讀操作是不需要上鎖的。
2..copyonwritearraylist:使用了無鎖計算,即當物件進行寫操作時,複製該物件;若進行讀,則直接返回結果,操作過程中不進行同步。這很好的利用了物件的不變性,在沒有對對像進行寫操作之前,由於物件未發生改變,因此不需要加鎖。而在試圖改變物件的時候,總是先獲得乙個物件的副本,然後對副本進行操作,最後將副本寫回。這種實現方式的核心思想時減少競爭,從而提高在高併發時的讀取效能。但是在一定程度上犧牲了寫的效能。
3.vector:使用了同步關鍵字,所有的get操作都需要先獲得鎖才能進行。在高併發的情況下過多的鎖操作會拖累系統的效能。
結論:在讀多寫少的環境下,使用copyonwritearraylist可以提高效能,但是在寫多讀少的環境下,應該使用vector.
與list相似,併發set也有乙個copyonwritearrayset,它實現了set介面,並且是執行緒安全的,它的內部完全依賴copyonwritearraylist,因此它的特徵和copyonwritearraylist一致,適用於讀多寫少的環境,如果是寫多讀少的環境可以使用collections.synchronizedset()得到乙個執行緒安全的set。
同理獲得乙個執行緒安全的map也可以使用collections.synchronizedmap(),但是在高併發的環境下這個map的效能不是最佳的。jdk專門提供了乙個cocurrenthashmap來支援高併發。而cocurrenthashmap之所以如此強大,是因為:
1. 其內部實現了鎖分離。
2. get()操作也是無鎖的。
concurrenthashmap是由segment陣列結構和hashentry陣列結構組成。segment是一種可重入鎖reentrantlock,在concurrenthashmap裡扮演鎖的角色,hashentry則用於儲存鍵值對資料。乙個concurrenthashmap裡包含乙個segment陣列,segment的結構和hashmap類似,是一種陣列和鍊錶結構, 乙個segment裡包含乙個hashentry陣列,每個hashentry是乙個鍊錶結構的元素, 每個segment守護者乙個hashentry陣列裡的元素,當對hashentry陣列的資料進行修改時,必須首先獲得它對應的segment鎖。
而hashtable則是使用了內部鎖,所有的操作全部都需要獲得內部鎖才能得以執行。
但是呢,使用所分離這樣的技術也有乙個缺點:當需要統計全域性變數時(比如count),我們需要獲得所有分段鎖才能夠執行。
JAVA併發程式設計學習
併發程式設計主要目的是為了在相同的時間內讓程式執行得更快或者處理更多的任務。為了實現這一目的,併發程式設計會面臨很多的挑戰。併發程式設計必然會帶來多執行緒之間的問題,比如上下文之間的切換,執行緒死鎖,以及硬體資源的限制。無論是單核還是多核處理器都支援多執行緒。在單核處理器中,cpu會給每個執行緒分配...
Java併發學習筆記(1) 併發程式設計基礎
執行緒的狀態 new 初始狀態,執行緒被new 出來,但還沒start 的狀態 runnable 指的是呼叫了start 方法,但還在等著cpu資源的狀態 running 乙個執行緒獲得了cpu資源,正在走的狀態 terminated 執行緒物件的run 方法走完了的狀態 blocked 執行緒被阻...
java併發程式設計學習(3)
銀行排隊叫號的場景如圖所示 有乙個出票機,按順序出票。有多個櫃檯叫號。對於這樣的場景,實現可以分為2部分,出票機和櫃檯。出票機public class ticketwindow implements runnable catch interruptedexception e 新建ticketwind...