我正在閱讀約CopyOnWriteArrayList
,並想知道如何在ArrayList
類中演示數據競賽。基本上我試圖模擬ArrayList
失敗的情況,所以它變得有必要使用CopyOnWriteArrayList
。有關如何模擬此的任何建議。Java中的數據競爭ArrayList類
4
A
回答
6
種族是當兩個(或多個)線程試圖在共享數據進行操作,並最終輸出取決於所述數據被訪問的順序(和該順序是不確定的)
維基百科:
競賽狀況或種族危害是電子系統或過程中的缺陷,其中過程的輸出和/或結果出乎意料且嚴重依賴於其他事件的順序或時間。該術語源於兩個信號相互競爭以首先影響輸出的想法。
例如:
public class Test {
private static List<String> list = new CopyOnWriteArrayList<String>();
public static void main(String[] args) throws Exception {
ExecutorService e = Executors.newFixedThreadPool(5);
e.execute(new WriterTask());
e.execute(new WriterTask());
e.execute(new WriterTask());
e.execute(new WriterTask());
e.execute(new WriterTask());
e.awaitTermination(20, TimeUnit.SECONDS);
}
static class WriterTask implements Runnable {
@Override
public void run() {
for (int i = 0; i < 25000; i ++) {
list.add("a");
}
}
}
}
然而,這使用ArrayList
時,與ArrayIndexOutOfbounds
失敗。這是因爲在插入之前應調用ensureCapacity(..)
以確保內部陣列可以保存新數據。這裏是發生了什麼:
- 第一個線程調用
add(..)
,進而調用ensureCapacity(currentSize + 1)
- 之前的第一個線程實際上已經增加了尺寸,第二個線程還呼籲
ensureCapacity(currentSize + 1)
。 - 因爲兩者已閱讀的
currentSize
初始值,內部陣列的新的大小是currentSize + 1
- 兩個線程使昂貴的操作舊數組複製到擴展之一,新的大小(其不能同時保留兩個添加)
- 然後,他們每個人都試圖將新元素分配到
array[size++]
。第一個成功,第二個失敗,因爲內部數組由於接收條件而沒有被正確地擴展。
出現這種情況,是因爲兩個線程試圖在同一時間對同一結構中添加項目,並加入其中一個已覆蓋了除其他的(即第一個丟失了)
CopyOnWriteArrayList
- 多線程的另一個好處寫
ArrayList
- 線程迭代的
ArrayList
。它一定會得到ConcurrentModificationException
以下是如何證明它:
public class Test {
private static List<String> list = new ArrayList<String>();
public static void main(String[] args) throws Exception {
ExecutorService e = Executors.newFixedThreadPool(2);
e.execute(new WriterTask());
e.execute(new ReaderTask());
}
static class ReaderTask implements Runnable {
@Override
public void run() {
while (true) {
for (String s : list) {
System.out.println(s);
}
}
}
}
static class WriterTask implements Runnable {
@Override
public void run() {
while(true) {
list.add("a");
}
}
}
}
如果你運行該程序多次,你經常會被你得到OutOfMemoryError
越來越ConcurrentModificationException
之前。
如果用CopyOnWriteArrayList
替換它,你沒有得到的異常(但程序很慢)
注意,這僅僅是一個示範 - 的CopyOnWriteArrayList
的好處是,當讀取數大大數量超過的寫入次數。
-2
兩個線程,一個遞增arraylist和一個遞減。數據競賽可能發生在這裏。
0
實施例:
for (int i = 0; i < array.size(); ++i) {
Element elm = array.get(i);
doSomethingWith(elm);
}
如果另一線程調用array.clear()該線程之前調用array.get(i)中,但它比較了後i相array.size(), - > ArrayIndexOutOfBoundsException異常。
相關問題
- 1. 數據競爭示例和數據競爭檢測示例
- 2. 數據庫競爭條件
- 3. 數據競爭時GOMAXPROCS = 1
- 4. 連續代碼中的數據競爭
- 5. WURFL的競爭對手java
- 6. Java/Android:LinkedList競爭條件
- 7. Java線程安全,數據競爭和良好的實現
- 8. SPECIAL POPL ISSUE的數據競爭示例Java Memory Model混淆
- 9. 避免與golang數據競爭工人
- 10. 避免數據存儲競爭
- 11. Helgrind報告單線程數據競爭
- 12. Magento數據庫競爭其他網站
- 13. 存儲位置和數據競爭
- 14. 競爭條件
- 15. 競爭條件
- 16. 競爭條件
- 17. 競爭條件
- 18. 競爭條件
- 19. 競爭條件
- 20. xv6中的競爭條件
- 21. 一個簡單的Java競爭條件
- 22. 的競爭條件
- 23. JBoss 7.1數據源JDBC 4.1 Java持久性競爭
- 24. 如何從div競爭中刪除競爭?
- 25. Java多線程競爭條件場景
- 26. Akka演員Java競爭消費者
- 27. 與文件getAbsolutePath競爭條件()java
- 28. 使用Java防止競爭條件
- 29. 競爭消費者
- 30. ASP.NET競爭條件
@Mark - 但問題是關於多線程,並且這個例外(如名稱所示)本質上是「多線程的」。 – Bozho 2010-10-01 07:02:25
似乎我並不完全明白。你能否說出數據競賽是如何引起的? – devnull 2010-10-01 07:33:35
@iJeeves看到更新 – Bozho 2010-10-01 08:27:11