In D, the preferred way to do multi-threading
is to rely on immutable
data and synchronize threads
using message passing. However, 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.
Use the shared
type identifier to mark variables
that are shared among different threads:
shared(int)* p = new int;
int* t = p; // ERROR
For example std.concurrency.send
only allows sending 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 are used to tell 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 in which case 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);