我试图了解SynchronizedMap,并运行了以下代码。我得到下面的输出,有一个异常(exception)。根据我的理解,当线程仍在执行对映射的写操作或线程处于 sleep 状态时,当get()方法尝试访问syncmap时,将导致异常。我的理解正确吗?还是我缺少什么?

class MapHelper1 implements Runnable {
Map<String, Integer> map;

public MapHelper1(Map<String, Integer> map) {
    this.map = map;
    new Thread(this, "MapHelper1").start();
}

public void run() {
    map.put("One", 1);
    try {
        System.out.println("MapHelper1 sleeping");
        Thread.sleep(100);
    } catch (Exception e) {
        System.out.println(e);
    }

}
}

class MapHelper2 implements Runnable {
Map<String, Integer> map;

public MapHelper2(Map<String, Integer> map) {
    this.map = map;
    new Thread(this, "MapHelper3").start();
}

public void run() {
    map.put("two", 1);
    try {
        System.out.println("MapHelper2 sleeping");
        Thread.sleep(100);
    } catch (Exception e) {
        System.out.println(e);
    }

}
}


class MapHelper3 implements Runnable {
Map<String, Integer> map;

public MapHelper3(Map<String, Integer> map) {
    this.map = map;
    new Thread(this, "MapHelper3").start();
}

public void run() {
    map.put("three", 1);
    try {
        System.out.println("MapHelper3 sleeping");
        Thread.sleep(100);
    } catch (Exception e) {
        System.out.println(e);
    }

}
}

public class MainClass {

public static void main(String[] args) {
    Map<String, Integer> hashMap = new HashMap<>();
    Map<String, Integer> syncMap = Collections.synchronizedMap(hashMap);
    MapHelper1 mapHelper1 = new MapHelper1(syncMap);
    MapHelper2 mapHelper2 = new MapHelper2(syncMap);
    MapHelper3 mapHelper3 = new MapHelper3(syncMap);



    for (Map.Entry<String, Integer> e : syncMap.entrySet()) {
        System.out.println(e.getKey() + "=" + e.getValue());
    }

}

}

输出:
MapHelper1 sleeping
MapHelper2 sleeping
MapHelper3 sleeping


Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1494)
at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1527)
at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1525)
at MainClass.main(MainClass.java:137)
Command exited with non-zero status 1

编辑:当生成输出时,我无异常(exception)地再次运行了几次代码。为什么会这样呢?

最佳答案

迭代时,您不同步访问。用:

synchronized(syncMap) {
  for (Map.Entry<String, Integer> e : syncMap.entrySet()) {
    System.out.println(e.getKey() + "=" + e.getValue());
  }
}

甚至在 synchronizedMap() 方法javadoc中


  Map m = Collections.synchronizedMap(new HashMap());
      ...
  Set s = m.keySet();  // Needn't be in synchronized block
      ...
  synchronized (m) {  // Synchronizing on m, not s!
      Iterator i = s.iterator(); // Must be in synchronized block
      while (i.hasNext())
          foo(i.next());
  }

关于java - SynchronizedMap ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48323357/

10-11 04:00