Java - 同步 List 上的 getSize()

标签 java multithreading synchronization

List<Ball> myObjs = myThreads[threadIndex].getMyObjList();
int initialSize = Collections.synchronizedList(myObjs).size();

抛出 ConcurrentModificationException。我也试过把这个放在 synchronized(myObjs) block ,但它也没有用。解决办法是什么?在我使用此列表的其他任何地方,它都在同步( block )中。

附言此错误最终还会产生 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() 根本不执行任何有意义的同步。没有其他线程可以获取创建的同步列表包装器,因此没有其他线程可以通过包装器与这个线程同步。

关于Java - 同步 List 上的 getSize(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11605927/

相关文章:

multithreading - 哪些参数有助于决定何时使用哪个 : Thread or ThreadPool or Task in C#

java - 在Java中的单独线程上循环音频

MySQL同步?

Java——同步 ArrayList 的最有效方法是什么?

java - Glassfish 2.x EJB 库丢失

java - If和Else If之间的区别?

java - 使用 Google+ API 发帖

java - LinkedLIst indexOf递归实现

c# - 是什么导致我的 c# WinForms 应用程序卡住/挂起?

ios - 需要有关在一个应用程序中在 iOS 设备之间同步数据的建议