Java同步HashMap中的size(),put(),remove(),get()是否为原子?

La-*_*eja 7 java multithreading synchronization atomic hashmap

我将Java Map声明为

Map<String, String> map = Collections.synchronizedMap(new HashMap<String, String>());
Run Code Online (Sandbox Code Playgroud)

处理并发问题,并在地图上同步其上的所有操作.但是,我读到synchronizedMap在操作是原子的时候不需要同步.我检查了Java API,HashMap的文档似乎没有提到哪些是原子的,所以我不确定是哪些.

我正在同步以下对地图的调用:

map.size()

map.put()

map.remove()

map.get()
Run Code Online (Sandbox Code Playgroud)

但如果有些是原子的,那么似乎并不需要同步.哪个是原子的?

cia*_*mej 11

顾名思义的同步映射是同步的.对其上的任何其他操作而言,其上的每个操作都是原子的.

您可以将其视为同步映射的每个方法都使用synchronized关键字声明.

请记住,虽然单个操作是原子操作,但如果将它们组合起来,它们就不再是原子操作,例如:

String value = map.get("key");
map.put("key", value+"2");
Run Code Online (Sandbox Code Playgroud)

不等于您的自定义同步代码:

synchronized (map) {
    String value = map.get("key");
    map.put("key", value+"2");
}
Run Code Online (Sandbox Code Playgroud)

反而:

synchronized (map) {
    String value = map.get("key");
}
synchronized (map) {
    map.put("key", value+"2");
}
Run Code Online (Sandbox Code Playgroud)


Ted*_*opp 5

A HashMap不保证具有原子操作.从不同的线程(偶数size())调用其任何方法可能会破坏映射.但是,使用Collections.synchronizedMapwill 获得的映射会使每个调用同步(因此是线程安全的).

但是,您可能需要更高级别的同步.例如,如果您测试是否存在密钥,读取大小,或以其他方式从地图访问某些内容,然后根据结果对地图执行其他操作,则地图可能在两次调用之间发生了更改.在这种情况下,您需要一个synchronized块来使整个事务成为原子,而不是同步映射(这只会使每个调用成为原子).