Although the preferred way in D to do multi-threading
is to rely on immutable
data and synchronize threads
using message passing, the language has built-in
support for synchronization primitives as well as
type system support with shared
to mark objects
that are accessed from multiple threads.
The shared
type identifier allows to mark variables
that are shared among different threads:
shared(int)* p = new int;
int* t = p; // ERROR
For example std.concurrency.send
just allows to send either
immutable
or shared
data and copying the message
to be sent. shared
is transitive so if a class
or struct
is marked shared
all its members will be too.
Note that static
variables aren't shared
by
default because they are implemented using
thread local storage (TLS) and each thread gets
its own variable.
synchronized
blocks allow to instruct the compiler
to create a critical section that can only be entered
by one thread at a time.
synchronized {
importStuff();
}
Within class
member functions these blocks might be
limited to different member objects mutexes
with synchronized(member1, member2)
to reduce
contention. The D compiler inserts critical
sections automatically. A whole class can be marked
as synchronized
as well and the compiler will
make sure that just one thread accesses a concrete
instance of it at a time.
Atomic operations on shared
variables can be
performed using the core.atomic.atomicOp
helper:
shared int test = 5;
test.atomicOp!"+="(4);