Channel Synchronization in D Programming Language

This example demonstrates how to use channels to synchronize execution across threads. We’ll use a blocking receive to wait for a thread to finish. When waiting for multiple threads to finish, you may prefer to use a core.sync.Barrier instead.

import std.stdio;
import core.thread;
import core.time;

// This is the function we'll run in a thread. The
// `done` channel will be used to notify another
// thread that this function's work is done.
void worker(shared bool* done)
{
    write("working...");
    Thread.sleep(dur!"seconds"(1));
    writeln("done");

    // Set the flag to notify that we're done.
    *done = true;
}

void main()
{
    // Create a shared boolean flag for synchronization
    shared bool done = false;

    // Start a worker thread, giving it a pointer to the flag
    auto workerThread = new Thread(() => worker(&done));
    workerThread.start();

    // Block until we receive a notification from the
    // worker that it's done
    while (!done) {
        Thread.yield();
    }
}

To run the program:

$ dmd -run channel-synchronization.d
working...done

If you removed the while (!done) loop from this program, the program would exit before the worker even started.

In D, we use shared memory and a boolean flag for synchronization instead of channels. The shared keyword ensures proper synchronization between threads. We use a while loop with Thread.yield() to efficiently wait for the worker thread to complete its task.

D’s approach to concurrency is different from some other languages, but it provides powerful tools for managing shared state and synchronization between threads.