[concurrency-interest] How bad can volatile long++ be?
Thomas.Hawtin at Sun.COM
Mon Dec 10 16:06:37 EST 2007
Boehm, Hans wrote:
> In Java, ++ on volatiles is not atomic. I strongly recommend against maintaining even statistical counters that way. Use either java.util.concurrent.atomic.AtomicLong or per-thread counters.
> The following non-Java anecdote from several years ago convinced me of this:
So, before java.util.concurrent?
> Our conservative garbage collector used to optionally maintain approximate counts of live objects this way, by having each GC thread increment a shared counter as it found a live object. There are as many GC threads as processors. After observing some misbehavior on a dual processor (2 sockets, 1 core/socket) machine, and tracking down what was going on, I discovered that:
> 1) Maintaining the shared counter slowed down the collector by about a factor of two, negating the benefit of running on two processors.
> 2) The final count was consistently off by about a factor of two.
> The cause for (1) was no doubt contention on the cache line containing the counter. As a result of that, both threads spent a lot of their time waiting on that cache line, and presumably the timing worked out such that there was a high probability the line got stolen between the load and the store of the ++, resulting in the loss of about half the updates.
I don't think AtomicLong is going to help there, as it is still sharing
a volatile. So thread-local (ThreadLocal) counters are presumably the
way to go, possibly using an unshared AtomicLong.
More information about the Concurrency-interest