On Sep 13, 2019, at 10:11, Richard Musil
For the atomic operations the lock is on the hardware level (i.e. implemented in the CPU, across the mem BUS, cache, etc.), from the user perspective, it looks only like executing a particular (atomic) op-code. (https://software.intel.com/en-us/node/506090).
Compared to the "Lock" which is an OS implementation (which possibly uses the hardware atomic operations internally), but is far more heavy, because it can block the thread. An atomic operation cannot.
I think you’re mixing up two levels here. A lock doesn’t have to just be a kernel lock object, and usually isn’t—usually you’d implement it with an atomic counter, and then only fall back to the kernel lock when you detect contention (the atomic compare-exchange failed or compare-increment returned 2 instead of 1). And you may even sleep-lock or spin-lock a few times before falling back to the kernel. So, when there’s not high contention, it’s not actually heavy. It is, however, obviously not lock-free. If you’re building systems that need to guarantee progress for all threads at all time, locks make that difficult. But the tradeoff is that locks are a lot easier to tune, and to compose, than atomic operations. For example, if you want to keep a dozen values in sync, so everyone sees either version N or all of them or version N+1 of all of them, that’s trivial with locks (just grab a single lock around all dozen updates), but a big pain, and very easy to get wrong, with atomic operations. Of course even locks aren’t friendly to compose, just less unfriendly than atomics. For an extreme (but not uncommon) example, let’s say you also need to guarantee that a failing process can only update all 12 values or none of them. But that the proposed mp.AtomicValue wouldn’t help there either.