[英]Java - synchronizing getSize() on List
List<Ball> myObjs = myThreads[threadIndex].getMyObjList();
int initialSize = Collections.synchronizedList(myObjs).size();
引發ConcurrentModificationException。 我也曾嘗試將其放在Synchronized(myObjs)塊中,但它也不起作用。 解決辦法是什么? 我在其他任何使用此列表的地方,它都位於synced(塊)中。
PS此錯誤也最終導致產生BrokenBarrierException。 (是的,我正在使用循環屏障進行同步)
編輯:這是堆棧跟蹤:
Exception in thread "Thread-3" java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1091)
at java.util.ArrayList$SubList.size(ArrayList.java:921)
at java.util.Collections$SynchronizedCollection.size(Collections.java:1573)
at Part2.Animation.processCollisions(MyClass.java:133) // This is the call to size()
編輯:循環看起來像
for (int threadIndex=0; threadIndex < numThreads; threadIndex++) {
List<Ball> myObjs = myThreads[threadIndex].getMyObjList();
int initialSize = Collections.synchronizedList(myObjs).size();
}
並且無論numThreads如何,當threadIndex = 1時都會發生異常。
查看某些List
類的源代碼,我看不到調用size()
會引發ConcurrentModificationException
可能性。 如果您向我們展示了堆棧跟蹤信息,將會有所幫助。
但是與此同時,您似乎對Collections.synchronizedList
功能有基本的誤解。 它的作用是創建並返回一個列表包裝器,以確保對同一包裝器實例的操作進行同步。
無論如何,它不會阻止線程對基礎列表執行不同步的操作。 即您剛剛包裝的列表對象。 如果線程具有基礎列表的引用,則它可以直接訪問它,而無需經過包裝器。 對於相同的基礎列表,使用不同的包裝程序進行同步操作也不起作用。 因此,如果您在同一列表上兩次調用Collections.synchronizedList
,則將創建兩個彼此不同步的不同包裝器。
因此,實際上您的Collections.synchronizedList(myObjs).size()
根本不執行任何有意義的同步。 沒有其他線程可以控制所創建的同步列表包裝器,因此沒有其他線程可以通過包裝器與之同步。
它是由subList()
引起的,與同步無關。
myObjs
是subList()的結果,實際上myObjs是原始List的視圖 。 如果原始List被修改,則在subList.size()
時會發生ConcurrentModificationException
。 這很有意義,視圖應該與其原始List保持一致。
相反,您可以獲得以下子列表:
List mySubList = new ArrayList(originalList.subList(a, b));
如果要修改具有2個或以上線程的列表,則應使用CopyOnWriteArrayList
。
“此數組在迭代器的生命周期內永不更改,因此不可能發生干擾,並且保證迭代器不會引發ConcurrentModificationException。”
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.