【问题标题】:Iterating over synchronized collection迭代同步集合
【发布时间】:2013-03-04 13:18:54
【问题描述】:
我在这里问了一个关于迭代 Vector 的问题,我得到了一些很好的解决方案。但我读到了另一种更简单的方法。我想知道这是否是好的解决方案。
synchronized(mapItems) {
Iterator<MapItem> iterator = mapItems.iterator();
while(iterator.hasNext())
iterator.next().draw(g);
}
mapItems 是一个同步集合:Vector。这是否使对Vector 的迭代从ConcurrentModificationException 安全?
【问题讨论】:
标签:
java
multithreading
vector
synchronized
【解决方案1】:
是的,它将使其免受ConcurrentModificationException 的影响,但代价是所有内容本质上都是单线程的。
【解决方案2】:
是的,我相信这将阻止ConcurrentModificationException。您正在Vector 上进行同步。 Vector 上所有修改它的方法也是synchronized,这意味着它们也会锁定同一个对象。因此,在您迭代 Vector 时,没有其他线程可以更改它。
此外,您在迭代 Vector 时不会自己修改它。
【解决方案3】:
简单地同步整个集合不会阻止 ConcurrentModificationException。这仍然会引发 CME
synchronized(mapItems) {
for(MapItem item : mapsItems){
mapItems.add(new MapItem());
}
}
【解决方案4】:
您可能需要考虑使用 ReadWriteLock。
对于迭代列表而不修改其内容的进程,获取共享 ReentrantReadWriteLock 的读锁。这允许多个线程对锁具有读取权限。
对于将修改列表的进程,获取共享锁上的写锁。这将阻止所有其他线程访问该列表(甚至是只读的),直到您释放写锁。
【解决方案5】:
这是否使对 Vector 的迭代安全
ConcurrentModificationException?
YES 它使对 Vector 的迭代从 ConcurrentModificationException 开始是安全的。如果它不同步,那么在这种情况下,如果您通过各种线程访问 Vector 并且其他一些线程正在结构上修改Vector在迭代器创建后的任何时候,迭代器都会抛出ConcurrentModificationException。
考虑运行这段代码:
import java.util.*;
class VVector
{
static Vector<Integer> mapItems = new Vector<Integer>();
static
{
for (int i = 0 ; i < 200 ; i++)
{
mapItems.add(i);
}
}
public static void readVector()
{
Iterator<Integer> iterator = mapItems.iterator();
try
{
while(iterator.hasNext())
{
System.out.print(iterator.next() + "\t");
}
}
catch (Exception ex){ex.printStackTrace();System.exit(0);}
}
public static void main(String[] args)
{
VVector v = new VVector();
Thread th = new Thread( new Runnable()
{
public void run()
{
int counter = 0;
while ( true )
{
mapItems.add(345);
counter++;
if (counter == 100)
{
break;
}
}
}
});
th.start();
v.readVector();
}
}
在我的系统中,它在执行时显示以下输出:
0 1 2 3 4 5 6 7 8 9
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at VVector.readVector(VVector.java:19)
at VVector.main(VVector.java:38)
但另一方面,如果您使包含Iterator 的代码块使用mapItems 作为锁同步访问Vector,它将阻止与Vector 相关的其他方法的执行,直到@987654329 @block 自动完成。
【解决方案6】:
如果我们在 while 循环中调用 add 方法,则会抛出异常。
synchronized(mapItems) {
Iterator<MapItem> iterator = mapItems.iterator();
while(iterator.hasNext())
iterator.next();
mapItems.add("Something"); // throws ConcurrentModificationException
}