Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using volatile long as an atomic

If I have something like this...

volatile long something_global = 0;

long some_public_func()
{
    return something_global++;
}

Would it be reasonable to expect this code to not break (race condition) when accessed with multiple threads? If it's not standard, could it still be done as a reasonable assumption about modern compilers?

NOTE: ALL I'm using this for is atomic increment and decrement - nothing fancier.

like image 813
Clark Gaebel Avatar asked Nov 27 '22 18:11

Clark Gaebel


2 Answers

No - volatile does not mean synchronized. It just means that every access will return the most up-to-date value (as opposed to a copy cached locally in the thread).

Post-increment is not an atomic operation, it is a memory access followed by a memory write. Interleaving two can mean that the value is actually incremented just once.

like image 72
danben Avatar answered Dec 04 '22 02:12

danben


No, you must use platform-dependent atomic accesses. There are several libraries that abstract these -- GLib provides portable atomic operations that fall back to mutex locks if necessary, and I believe Boost also provides portable atomics.

As I recently learned, for truly atomic access, you need a full memory barrier which volatile does not provide. All volatile guarantees is that the memory will be re-read at each access and that accesses to volatile memory will not be reordered. It is possible for the optimizer to re-order some non-volatile access before or after a volatile read/write -- possibly in the middle of your increment! -- so you must use actual atomic operations.

like image 41
Michael Ekstrand Avatar answered Dec 04 '22 01:12

Michael Ekstrand