Подтвердить что ты не робот

Являются + =, | =, & = и т.д. Атомами?

Являются ли операторы "изменить" такими, как +=, |=, &= и т.д. atom?

Я знаю, что ++ является атомарным (если вы выполняете x++; в двух разных потоках одновременно), вы всегда окажетесь x увеличено на 2, а не x=x+1, при выключенной оптимизации).

Интересно, существует ли variable |= constant, а подобные - поточно-безопасные или мне нужно их защищать с помощью мьютекса?

(... или он зависит от процессора? В этом случае, как это делается на ARM?)

4b9b3361

Ответ 1

Вы ошибаетесь. Нет никакой гарантии, что ++ является атомарным и не существует для составных операторов присваивания или даже для любой операции на С++.

Ответ 2

x++ часто реализуется в трех инструкциях: Прочитайте X в регистр, Increment it и запишите его обратно в память.

Ваша нить может быть предварительно удалена между любыми из них.

Ответ 3

Для изменения значения, которое должно быть видимым по всем ядрам, a + = (например) должно было бы загрузить значение, добавить инкремент и затем сохранить его. Это означает, что операция не будет атомарной.

Чтобы обеспечить атомарность, вам необходимо установить соответствующую блокировку операции.

Ответ 4

Нет, они не атомные! Если вам нужны атомарные операции над примитивными типами, и вы используете linux, вы можете посмотреть здесь: http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html и/или атомный .h...

Ответ 5

++ может быть атомарным на вашем компиляторе/платформе, но в спецификациях С++ он не определен как атомарный.

Если вы хотите, чтобы изменить значение в атомном режиме, вы должны использовать соответствующие методы, такие как Interlocked * на окнах.

То же самое для всех других подпрограмм. Если вам нужны атомные операции, вы должны использовать соответствующие вызовы, а не стандартные.

Ответ 6

Оператор

Нет на C или С++ гарантированно является атомарным. Они могут быть на вашей платформе, но вы не будете знать точно. Как правило, единственной операцией, которая является атомарной, является команда Test и Set, которая обычно доступна на большинстве современных процессоров в той или иной форме в качестве основы для реализации семафоров.

Ответ 7

Это зависит как от компилятора, так и от процессора. Некоторые наборы инструкций предоставляют атомарные инструкции для этих (на машинных размерах).

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


В частности, на ARM: Команды ORR/ADD/AND принимают два операнда и помещают результат в регистр. Любой операнд может быть тем же регистром, что и регистр результатов, поэтому они могут использоваться как атомный | =, + =, & =.

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

Ответ 8

Они не только атомарны, как и все операции, но могут иметь очень интересные результаты. Например, если компилятор видит, что он пишет в x, разрешено использовать x в качестве временной переменной, а не использовать регистры или пространство стека. Это означает, что x может временно содержать ЛЮБОЕ значение, а не только значения, которые имеют смысл для x

http://software.intel.com/en-us/blogs/2013/01/06/benign-data-races-what-could-possibly-go-wrong

Ответ 9

Здесь был указан дубликат, и для этого требуется обновление. "Новый" язык C11 допускает атомный атрибут, который допускает следующее:

_Atomic int a;
...
a += 3

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

1: в некоторых архитектурах атомные операции возможны только в памяти, которая поддерживает определенные протоколы доступа. ARMv7, MIPS, например, превращают последовательность в:

do {
    x = LoadLinked(a) + 3;
} while !StoreConditional(x, &a);

но LoadLinked/StoreConditional - undefined для некоторых типов памяти/кеша. Наслаждайтесь отладкой.

2: Связано это ложное совместное использование, которое является артефактом LoadLinked, StoreConditional работает в строках кэша (например, 32, 64, 256 байт), а не подблоках. Так:   _Atomic int a [4]; может потребоваться размер строки в 4 * кеша (таким образом, 1024 байта), чтобы безопасно разрешать одновременные атомарные операции на [n] и [n + 1], поскольку 4 cpus могут приближаться к обновлению [0..3], но никогда не удается,

Надеемся, что следующий стандарт распознает присущий им отказ от украшения атрибута и восстановит c89 как законный стандарт C.

Ответ 10

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

Ответ 11

Даже если ++ является атомной операцией, это не означает, что два потока, выполняющие ++x, приведут к тому, что x будет ровно на два выше. Вам нужно как-то синхронизировать потоки, иначе они не обязательно будут видеть изменения друг друга.

Ответ 12

Вы должны защитить свою переменную, например, мьютексом