vector同步實現方式是在方法上新增synchronized同步。synchronizedlist方法得到的執行緒安全容器是建立乙個鎖物件,每個操作都給這個物件加鎖,讓當前執行緒持有這個鎖,簡單的說就是鎖的物件不同,vector是synchronized(this),synchronizedlist是synchronized(obj),建議用
collections.synchronizedcollection()方法獲得執行緒安全的容器。
這裡說的執行緒安全僅是指單個方法呼叫能保持原子性,如add,remove等,當復合操作時,還需要自己解決併發問題,否則就會有問題,比如下面這段**:
當多執行緒呼叫時,如a執行緒呼叫getlast,獲得到lastindex值為10時,執行緒b執行了整個deletelast方法,執行緒a在執行get方法時就會報錯。
所以執行緒安全的容器用著不一定就執行緒安全,執行緒安全的容器只是說底層的操作執行緒安全,使用者自己的復合操作還需要自己進行同步。
jdk的api中也明確指出了,如果要對synchronizedcollection方法生成的同步容器進行迭代操作,必須要手動在返回的容器上進行同步操作,如上面的操作可以這樣:
類似的還有迭代同步容器也要加上同步操作,如:
這種迭代如果在單執行緒情況下,或者併發情況下迭代時沒有其他執行緒刪除元素才能正常使用,如果併發情況下乙個執行緒正在迭代容器,另乙個執行緒修改了容器(如增刪元素),就會導致異常,這種併發情況下,則需要手動加上同步:
其實就是當乙個執行緒正在迭代乙個同步容器時,發現了這個容器被其他執行緒修改(增加或刪除元素)了,就會丟擲乙個concurrentmodificationexception異常。
有人會說,迭代乙個容器需要加上同步,這也太麻煩了,的確非常麻煩,而且dosomething執行時始終持有乙個鎖,還可能造成死鎖等。最好的辦法是從設計上避免這種情況(後面也會有其他方式避免),盡量在單執行緒中使用集合,比如轉殖容器獲得乙個副本,對副本進行迭代,將副本封閉在乙個執行緒內,雖然能避免加鎖,不過這樣有很大的效能開銷。實際場景中是用同步還是用轉殖,還是其他方法等,需要根據實際情況綜合考慮(如容器大小,操作時間,頻率等)。
最後說說concurrentmodificationexception,上面說了當乙個執行緒正在遍歷乙個同步容器時,發現了這個容器被其他執行緒修改了,就會丟擲這個異常,很多時候隱式的呼叫容器方法都會進行遍歷,比如tostring()、hashcode()、equals()、containsall()、removeall()、retainall()或者將容器作為引數的建構函式等等,都會直接或間接的對容器進行迭代,都有可能丟擲concurrentmodificationexception,這個開發時一定要小心。
java併發程式設計實戰 基礎構建模組2
1,通過併發容器來替代同步容器,可以極大地提高伸縮性並降低風險 2,concurrenthashmap 2.1,用來替代同步的map,同map一樣也是基於雜湊的map。2.2,但是它使用一種更加細粒度的加鎖機制 分段鎖lockstriping 來實現大程度的共享。2.3,它允許多個執行緒同時對容器進...
Java併發程式設計基礎構建模組(01) 同步容器類
vector同步實現方式是在方法上新增synchronized同步。synchronizedlist方法得到的執行緒安全容器是建立乙個鎖物件,每個操作都給這個物件加鎖,讓當前執行緒持有這個鎖,簡單的說就是鎖的物件不同,vector是synchronized this synchronizedlist...
Java併發程式設計實戰 第5章 基礎構建模組
同步容器類 併發容器 阻塞佇列和生產者 消費者模式 序列執行緒封閉 執行緒間轉移物件所有權,之前的所有者不會再訪問它 deque blockingdeque 對queue和blockingqueue進行擴充套件 工作密取 乙個工作者要訪問另乙個工作者的佇列,會從尾部獲取,降低佇列上的競爭程度 阻塞方...