Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't JVM compile "incrementing a int variable" as an atomic Fetch-and-Increment opereation?

I've learned that incrementing a int variable in Java is NOT a atomic operation, however, I found that CPUs support atomic Fetch-and-Increment operation.

So my question is, why JVM doesn't compile incrementing a int variable operation to an atomic Fetch-and-Increment operation that CPUs support, which could be useful in multi-thread programming.

Early processors had atomic test-and-set, fetch-and-increment, or swap instructions sufficient for implementing mutexes that could in turn be used to implement more sophisticated concurrent objects.

--Java Concurrency in Practice

like image 749
user2916610 Avatar asked Feb 08 '23 11:02

user2916610


1 Answers

So my question is, why JVM doesn't compile incrementing a int variable operation to an atomic Fetch-and-Increment operation that CPUs support, which could be useful in multi-thread programming.

Because on typical modern CPUs, atomic read-modify-write operations (such as incrementing) are dozens of times more expensive than their corresponding non-atomic operations. And it would provide no benefit -- code can't rely on the operations being atomic because they're not guaranteed to be atomic. So what would the benefit be?

Though it's not directly relevant to your question, because so many other people have explained this incorrectly, I'll explain the two differences between an atomic increment and a non-atomic increment (at the hardware level):

  1. An atomic increment cannot overlap certain other operations in that same core. That is, it must take place at some specific time. This means that CPU instruction pipelining is typically severely negatively impacted by atomic operations.

  2. To prevent another thread from overlapping an operation to the same cache line in the middle of our atomic operation (between the read and the write), the cache line is locked during the atomic operation. If another core attempts to take the cache line from the CPU executing the atomic operation, even for a non-atomic operation, it will have to wait until the atomic operation completes. (This used to be a bus lock. Modern CPUs are much smarter.)

Of course, there's no guarantee that every CPU will be the same, but modern CPUs that have multiple cores and popular Java implementations are nearly certain to have multi-core operations highly optimized. Future CPUs, of course, may be even better.

Also, to correct another common misconception: The caches on modern multi-core CPUs communicate directly. They never need to go through main memory to synchronize CPUs (except perhaps in the rare case where the data needed is only in main memory and for some reason couldn't be prefetched). If data is in one core's cache, it can go directly to another core's cache using a variant of the MESI protocol. This is a good thing -- multi-core CPUs would perform pretty terribly if inter-core synchronization had to go through RAM.

like image 64
David Schwartz Avatar answered Feb 11 '23 01:02

David Schwartz