атомарные записи и летучие чтения

Я разрабатываю многопоточный алгоритм, в котором требуется прочитать последнее значение разделяемой переменной. Записи в переменную являются атомарными (используя сравнение и обмен). Однако чтения не являются атомарными.

Рассмотрим следующий пример:

//Global variable
int a = 10;// Thread T1
void func_1() {
__sync_bool_compare_and_swap(&a, 10, 100);
}

// Thread T2
void func_2() {
int c = a;
/* Some Operations */
int b = a;
/* Some Operations */
}

Если код int b = a выполняется (потоком T2) после __sync_bool_compare_and_swap в func_1 (по потоку T1), тогда, как я понимаю, до сих пор не гарантируется чтение последнего значения «variable a», поскольку компилятор может кэшировать «a» и использовать старое значение «a».

Теперь, чтобы избежать этой проблемы, я объявил переменную «volatile», как показано ниже:

volatile int a = 10;

// Thread T1
void func_1() {
__sync_bool_compare_and_swap(&a, 10, 100);
}

// Thread T2
void func_2() {
volatile int c = a;
/* Some Operations */
volatile int b = a;
/* Some Operations */
}

По тому же сценарию выполнения int b = a потоком T2 после __sync_bool_compare_and_swap потоком T1 закончен, гарантированно прочитано последнее значение «а»?

Как повлияет когерентность кэша и модель согласованности памяти на энергозависимое чтение после атомарной записи?

1

Решение

На всех платформах, которые вы, вероятно, будете использовать, которые поддерживают C ++ и несколько потоков, чтение из выровненного, выровненного int будет атомным и будет читать последние значения. Однако это абсолютно не гарантируется стандартом C ++. Может быть какая-то платформа, где она не работает, и она может не работать со следующей ЦП, версией компилятора или версией ОС.

В идеале используйте то, что гарантированно обеспечит атомарность и видимость. C ++ — 11 Atomic, вероятно, лучший выбор. Встроенные функции компилятора будут следующим лучшим выбором. Если у вас нет выбора, кроме как просто использовать volatileЯ бы посоветовал вам использовать тесты препроцессора, чтобы подтвердить, что вы находитесь на платформе, где, как известно, этого достаточно, и выдать ошибку (с #error) если не.

Обратите внимание, что на каждой платформе, которую вы, вероятно, будете использовать, кэши памяти ЦП совершенно не имеют значения, поскольку они становятся невидимыми из-за согласованности аппаратного кэша. На всех платформах, которые вы, вероятно, будете использовать, проблемы заключаются только в оптимизации компилятора, предварительно выбранных чтениях и опубликованных записях.

0

Другие решения

volatile Ключевое слово только гарантирует, что компилятор не будет хранить переменную в регистре и вместо этого будет загружать переменную из памяти каждый раз, когда она используется. Он не имеет ничего общего с моделями кеша или согласованности памяти системы, в которой он работает.

3

volatile не делает операции чтения атомарными. Неатомарное чтение одновременно с (атомарной) записью приводит к неопределенному поведению. Используйте атомарное чтение в любой форме, либо std::atomic или внутренние. Не использовать volatile для любой формы параллелизма.

Атомное чтение само по себе не гарантирует, что значение будет самый последний. В вашем случае поток T2 может никогда не читать 100, в теории. Стандарт гласит, что реализация (аппаратная часть, ОС и т. Д.) Должна делать все возможное, чтобы записи были видны другим потокам за конечное время. Возможно, здесь невозможно поставить формальные требования.

С помощью дополнительной синхронизации вы можете добиться более ограниченного поведения:

std::atomic<int> a = 10;
std::atomic<bool> done = false;

void func_1() {
int old = 10;
if (a.compare_exchange_strong(old, 100))
done.store(true);
}

void func_2() {
bool is_done = done.load();
int b = a.load();
assert(b == 100 || !is_done);

while (!done.load()); // May spin indefinitely long, but should not do that
assert(a.load() == 100);
}

На самом деле, чтобы поймать это простое атомарное чтение, не самый последний значение, нужно было бы поставить достаточно синхронизации в программу (чтобы определить самый последний) так что он будет работать правильно.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector