www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Atomic vs Mutex

reply Jonathan <JonathanILevi gmail.com> writes:
Everywhere I look the advice is to avoid atomic and just mutex 
things.

Why is this `a.atomicStore(b)`(memory order is seq) less safe 
than `synchronized{a=b}`?  I get that when more operations or 
shared values are used it is appropriate to mutex the entire set 
of operations but why would I for a single set?

If the first is in fact less safe that the second then I am eager 
to learn more, could you recommend a book or paper on the subject?

Thanks!
Mar 26 2018
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Monday, March 26, 2018 23:15:42 Jonathan via Digitalmars-d-learn wrote:
 Everywhere I look the advice is to avoid atomic and just mutex
 things.

 Why is this `a.atomicStore(b)`(memory order is seq) less safe
 than `synchronized{a=b}`?  I get that when more operations or
 shared values are used it is appropriate to mutex the entire set
 of operations but why would I for a single set?

 If the first is in fact less safe that the second then I am eager
 to learn more, could you recommend a book or paper on the subject?
I think that what it mostly comes down to is that it's harder to get atomics right than it is to get mutexes right. It can be very difficult to write lock-free code - especially when you're dealing with more complicated objects like containers. It can already be surprisingly difficult to get mutexs right. People screw up thread-safety stuff all the time. The fact that D uses thread-local by default reduces the problem, but then folks frequently get annoyed with the restrictions that shared has and end up using __gshared, throwing away all of the protections and risking bugs due to the fact that the compiler assumes that the objects are thread-local. The biggest thing that you can do in a program to make it thread-safe is to make as much as possible thread-local and have as little as possible shared between threads. Also, it's frequently considered better practice to use message passing such as you get with std.concurrency than directly sharing data. Unfortunately, I don't really have any reading that I could recommend on the subject. There's always the section on concurrency in TDPL (which IIRC is a chapter which is actually available for free), but it's mostly talking about the D-specific issues and doesn't say anything about atomics (IIRC, core.atomic didn't even exist when TDPL was written). I expect that there are quite a few resources online talking about C++ atomics though. IIRC, their API goes about things in a different way, but the basic concepts are the same. All of the basic concepts are the same in C++ as they are in D. It's just that D objects are thread-local by default, which means that the type system helps you keep things thread-safe in a way that C++ doesn't. With shared, you're generally forced to cast it away while the mutex is locked, whereas in C++, since there is no shared, it just lets you muck with shared objects as if they were thread-local without any casting. In D, atomics are pretty much the only way to do much with shared without casting it away in protected sections of code. - Jonathan M Davis
Mar 26 2018