8

我在这里问了一个关于迭代 a 的问题Vector,我得到了一些很好的解决方案。但我读到了另一种更简单的方法。我想知道这是否是一个好的解决方案。

synchronized(mapItems) {
    Iterator<MapItem> iterator = mapItems.iterator();
    while(iterator.hasNext())
        iterator.next().draw(g);
}

mapItems 是一个同步集合:Vector。这是否使迭代Vector安全ConcurrentModificationException

4

6 回答 6

3

ConcurrentModificationException是的,它将以牺牲本质上是单线程的一切为代价使其安全。

于 2013-03-15T17:55:41.970 回答
2

是的,我相信这将防止ConcurrentModificationException. 您正在同步Vector. 修改它的所有方法Vector也是synchronized,这意味着它们也会锁定同一个对象。Vector因此,在您对其进行迭代时,没有其他线程可以更改。

Vector此外,您在迭代时不会修改自己。

于 2013-03-15T17:58:17.840 回答
2

简单地同步整个集合不会阻止 ConcurrentModificationException。这仍然会引发 CME

synchronized(mapItems) {
   for(MapItem item : mapsItems){
      mapItems.add(new MapItem());
   }
}
于 2013-03-15T18:25:51.827 回答
1

您可能需要考虑使用 ReadWriteLock。

对于迭代列表而不修改其内容的进程,获取共享 ReentrantReadWriteLock 的读锁。这允许多个线程对锁具有读访问权。

对于将修改列表的进程,获取共享锁上的写锁。这将阻止所有其他线程访问列表(甚至是只读的),直到您释放写锁。

于 2013-03-15T18:15:19.907 回答
1

这是否使对 Vector 的迭代不受 ConcurrentModificationException 的影响?

的,它使对 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)

但另一方面,如果您使用 as 锁使包含Iterator访问该Vector同步的代码块mapItems,它将阻止与该块相关的其他方法的执行,Vector直到该synchronized 块以原子方式完成。

于 2013-03-15T18:19:35.170 回答
0

如果我们在 while 循环中调用 add 方法,则会引发异常。

synchronized(mapItems) {
    Iterator<MapItem> iterator = mapItems.iterator();
    while(iterator.hasNext())
        iterator.next();
         mapItems.add("Something");  //  throws ConcurrentModificationException
}
于 2013-03-15T19:17:13.220 回答