10

Is the method ConcurrentHashMap.putAll(Map) supposed to be atomic?

I cannot find it in the documentation and it is not mentioned in the ConcurrentMap interface, so I guess the answer is no. I am asking it to be sure, since it wouldn't make sense if that operation wasn't atomic to be honest.

If it isn't atomic, what would be the best way to support atomic inserts of multiple items? Back to the good old synchronized?

Japer D.
  • 754
  • 1
  • 9
  • 18

4 Answers4

12

It's not atomic, no. According to the class documentation:

For aggregate operations such as putAll and clear, concurrent retrievals may reflect insertion or removal of only some entries.

To atomicize it, you'll have to use synchronized, yes. There's no non-blocking way to do this.

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • What about another (non-standard) concurrent Map implementation? –  Dec 14 '11 at 23:53
  • @pst Which could be a candidate? – Japer D. Dec 14 '11 at 23:54
  • @JaperD. I have no idea. Just wondering if you had any insight, although this answer is still complete without. –  Dec 15 '11 at 00:00
  • 1
    @pst: It's a good question. Without knowing the precise use-caes, but in general, I'd guess that it would be counterproductive. ConcurrentHashMap is what you might call "probabilistically concurrent": it's not completely non-blocking, but it works by being split internally into a fixed number of segments (default 16, but settable in the constructor), in the hopes that when multiple different threads write to a map concurrently, they will *probably* write to entries that are in different segments. If they do write to the same segment, then some amount of blocking is possible. (continued) – ruakh Dec 15 '11 at 00:19
  • 1
    (continued) For `putAll` to be atomic, you'd have to get rid of that completely (since you can't atomically report that multiple segments are updated). That said, it depends on your distribution of operations. If you expect normal `put`s to be relatively rare, but expect to have lots of `get`s and `putAll`s, then it could make sense to create a subclass of `HashMap` that uses a `ReadWriteLock` to control access: all reads would be wrapped in a read-lock, and all writes, including the whole of `putAll`, would be wrapped in a write-lock. – ruakh Dec 15 '11 at 00:23
  • Thanks for the info. I am creating a transaction mechanism. So all changed objects must be made visible at once when the transaction is committed. That's why I wanted putAll to be atomic. – Japer D. Dec 15 '11 at 00:35
  • @JaperD.: In that case, a `ReadWriteLock` may well be the way to go. (Though, contrary to my above suggestion to extend `HashMap`, it probably makes sense to create a wrapper for it that implements only the methods you need; "has-a" rather than "is-a". Otherwise you'd have to override every single method.) – ruakh Dec 15 '11 at 00:44
3

at the top of the doc

For aggregate operations such as putAll and clear, concurrent retrievals may reflect insertion or removal of only some entries.

ratchet freak
  • 47,288
  • 5
  • 68
  • 106
2

To atomicize it, you'll have to use synchronized, yes

Not only that: you have to put a synchronized block around every public map method thus degrading concurrency.

OlliP
  • 1,545
  • 11
  • 22
2

putAll() is not atomic, but merely has the guarantee that each individual put() is atomic.

eboix
  • 5,113
  • 1
  • 27
  • 38