同步容器和并发容器的区别
生活随笔
收集整理的這篇文章主要介紹了
同步容器和并发容器的区别
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
同步容器:可以簡單地理解為通過synchronized來實現同步的容器,如果有多個線程調用同步容器的方法,它們將會串行執行。比如Vector,Hashtable,以及Collections.synchronizedSet,synchronizedList等方法返回的容器。這些類實現線程安全的方式是:將他們的狀態封裝起來,并對每個公有的方法都進行同步,使得每次只有一個線程能訪問容器的狀態。
同步容器都是線程安全的,但是在某些情況下我們可能需要額外的客戶端加鎖來保護復合操作。容器上常見的符合操作包括:迭代,跳轉,以及條件運算。在同步容器類的內部,這些復合操作時線程安全的,但是當其他線程并發的修改容器時,他們可能會有意外的行為。
public static Object getLast(Vector list) { int lastIndex = list.size() - 1; return list.get(lastIndex); } <span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.2px;"> </span><pre name="code" class="java">public static void deleteLast(Vector list) { int lastIndex = list.size() - 1; list.remove(lastIndex); } ?雖然上面的方法看起來沒有問題,Vector自身的方法也是同步的,但是在多線程環境中還是隱藏著問題。如果有兩個線程A,B同時調用上面的兩個方法,假設list的大小為10,這里計算得到的lastIndex為9,線程B首先執行了刪除操作(多線程之間操作執行的不確定性導致),而后線程A調用了list.get方法,這時就會發生數組越界異常。導致問題的原因就是上面的復合操作不是原子操作,這里可以通過在方法內部使用list對象鎖來實現原子操作。
解決的方法一:使用客戶端加鎖的機制,通過過得容器類的鎖,我們可以使得如下的兩個方法稱為原子類操作。但是該方法會降低并發性,犧牲了伸縮性。
<pre name="code" class="java">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); } }
同步容器將所有對容器的訪問都串行化,以實現他們的線程安全性,這種方法的代價是嚴重降低并發性,當多個線程競爭訪問容器的鎖時,吞吐量將會嚴重減低。
并發容器:針對多個線程設計的,用并發容器來代替同步容器,可以極大地提高伸縮性并降低風險。 如ConcurrentHashMap,CopyOnWriteArrayList等。并發容器使用了與同步容器完全不同的加鎖策略來提供更高的并發性和伸縮性,例如在ConcurrentHashMap中采用了一種粒度更細的加鎖機制,可以稱為分段鎖,在這種鎖機制下,允許任意數量的讀線程并發地訪問map,并且執行讀操作的線程和寫操作的線程也可以并發的訪問map,同時允許一定數量的寫操作線程并發地修改map,所以它可以在并發環境下實現更高的吞吐量。
總結
以上是生活随笔為你收集整理的同步容器和并发容器的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【神经网络】一文读懂LSTM神经网络
- 下一篇: android程序的入口点,常见andr