C ++ 11 Порядок атомарной памяти с неатомарными переменными

Я не уверен в том, как гарантии упорядочения памяти атомарных переменных в c ++ 11 влияют на операции с другой памятью.

Допустим, у меня есть один поток, который периодически вызывает функцию записи для обновления значения, и другой поток, который вызывает чтение для получения текущего значения. Гарантируется ли, что последствия d = value; не будет видно до воздействия a = version;и будет видно до воздействия b = version;?

atomic<int> a {0};
atomic<int> b {0};
double d;

void write(int version, double value) {
a = version;
d = value;
b = version;
}

double read() {
int x,y;
double ret;
do {
x = b;
ret = d;
y = a;
} while (x != y);
return ret;
}

5

Решение

Гарантируется ли, что последствия d = value; не будет видно до воздействия a = version;и будет видно до воздействия b = version;?

Да, это. Это потому что последовательный барьер согласованности подразумевается при чтении или записи atomic<> переменная.

Вместо хранения version тег в два атомарные переменные до изменения значения и после него, вы можете увеличивать не замужем атомная переменная до и после модификации:

atomic<int> a = {0};
double d;

void write(double value)
{
a = a + 1; // 'a' become odd
d = value; //or other modification of protected value(s)
a = a + 1; // 'a' become even, but not equal to the one before modification
}

double read(void)
{
int x;
double ret;
do
{
x = a;
ret = value; // or other action with protected value(s)
} while((x & 2) || (x != a));
return ret;
}

Это известно как seqlock в ядре Linux: http://en.wikipedia.org/wiki/Seqlock

1

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

Правило таково, что, учитывая write поток, который выполняется один раз, и ничего больше, что изменяет a, b или же d,

  • Ты можешь читать a а также b из другого потока в любое время, и
  • если ты читаешь b и посмотреть version хранится в нем, то
    • Ты можешь читать d; а также
    • То, что вы прочитаете, будет value,

Обратите внимание, что истинность второй части зависит от порядка в памяти; это верно по умолчанию (memory_order_seq_cst).

3

Ваш объект d записывается и читается двумя потоками и не является атомарным. Это небезопасно, как предлагается в стандарте C ++ по многопоточности:

1.10 / 4 Две оценки выражений конфликтуют, если одна из них изменяет ячейку памяти, а другая обращается или изменяет ту же ячейку памяти.

1.10 / 21 Выполнение программы содержит гонку данных, если она содержит два конфликтующих действия в разных потоках, по крайней мере, один из
который не является атомным, и ни один не происходит раньше другого. Любое такое
гонка данных приводит к неопределенному поведению.

Важное редактирование:

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

тем не менее, цикл вашего читателя заканчивается на основе проверки окружающих атомных переменных, для которых есть строгие гарантии. При условии, что version никогда не повторяется между разными вызовами писателя и в обратном порядке, в котором вы приобретаете их значение:

  • порядок d читать по сравнению с d Писать не может быть неудачным, если два атома равны.
  • аналогично, значение чтения не может быть противоречивым, если две атомные группы равны.

Это означает, что в случае неблагоприятного состояния гонки на вашем неатомном, благодаря петле, вы в конечном итоге прочитаете последний value,

2
По вопросам рекламы [email protected]