Menu

Синхронизация и разделение данных

Хотя в D предпочтительным методом организации многопоточности является использование immutable данных и синхронизация посредством обмена сообщениями, язык также предлагает встроенную поддержку примитивов синхронизации и поддержку на уровне типов, с применением ключевого слова shared для обозначения объектов, доступ к которым осуществляется из нескольких потоков.

Квалификатор типа shared позволяет пометить переменные, разделяемые между различными потоками:

shared(int)* p = new int;
int* t = p; // ОШИБКА

Например, функция std.concurrency.send позволяет передавать только immutable или shared данные и копирует сообщение перед отправкой. shared транзитивно, и если класс или структура помечены shared, все их члены также будут помечены. Обратите внимание, static-переменные по умолчанию не являются shared, т.к. хранятся в локальном хранилище потока (TLS), и каждый поток получает собственную переменную.

Блоки synchronized позволяют указать компилятору необходимость создания критической секции, в которую потоки могут входить только по одному.

synchronized {
    importStuff();
}

При определении функций-членов класса, такие блоки можно разграничить посредством членов-мьютексов, с использованием synchronized(член1, член2), для снижения нагрузки на ресурс. Компилятор D автоматически вставит критические секции. Также можно весь класс пометить как synchronized, в этом случае компилятор гарантирует, что только один поток имеет доступ к объекту в отдельно взятый момент.

Атомарные операции над shared-переменными можно производить посредством вспомогательной функции core.atomic.atomicOp:

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

Подробнее

rdmd playground.d