【问题标题】: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
            }
            

            【讨论】:

              猜你喜欢
              • 2021-10-22
              • 2010-12-19
              • 2016-08-13
              • 1970-01-01
              • 1970-01-01
              • 2015-09-07
              • 2023-01-12
              • 2011-04-25
              • 1970-01-01
              相关资源
              最近更新 更多