Синхронізація та загальний доступ

У мові D найкращим способом створити багатопоточність є покладання на незмінні (immutable) дані і синхронізування потоків, використовуючи передачу повідомлень. Мова D має вбудовану підтримку синхронізації примітивів, а також підтримку типу з ключовим словом загальнодоступні (shared) для позначення доступних з кількох потоків об'єктів.

Ідентифікатор типу shared дозволяє позначати змінні, які використовуються різними потоками:

shared(int)* p = new int;
int* t = p; // ПОМИЛКА

Наприклад, std.concurrency.send дозволяє відправляти незмінні або загальнодоступні дані, а також копіювати повідомлення для відправки. Загальнодоступні дані є транзитними, відповідно, якщо класс або структура позначені як shared, всі їх члени будуть позначені так само. Зверніть увагу, що змінні static не є shared за замовчуванням і будуть реалізовані за допомогою локальної пам'яті потоку (ЛПП), де кожен потік отримає власну змінну.

synchronized блоки дозволяють повідомити компілятору, що дана секція є критичною і має бути доступна лише для одного потоку в один проміжок часу.

synchronized {
    importStuff();
}

У межах класу ці блоки можуть бути обмежені різними об'єктами м'ютекс із synchronized(member1, member2) для того, щоб обмежити багатопоточність. Копмілятор D автоматично вставляє критичні секції. Цілий клас також може бути позначений як synchronized, у той же час, компілятор повинен переконатися, що тільки один потік має доступ до певної копії.

Атомарні операції на змінних shared можуть бути реалізовані за допомогою помічника core.atomic.atomicOp:

shared int test = 5;
test.atomicOp!"+="(4);

Поглиблення

rdmd playground.d