Atomic vs Mutex

Jonathan M Davis newsgroup.d at jmdavisprog.com
Tue Mar 27 01:23:44 UTC 2018


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



More information about the Digitalmars-d-learn mailing list