Ответ 1
Операция - это действительно две операции.
__sync_fetch_and_add( &var, num )
Загрузка num
является атомарной. Добавление его в var
является атомарным. Но две атомные операции не выполняют атомную операцию при объединении. Вот почему так сложно изобретать новые блокированные структуры данных. Как правило, две поточно-безопасные операции не обязательно обеспечивают потокобезопасную работу при составлении. Вот почему так сложно делать правильные многопоточные приложения.
Вы видите, что __sync_fetch_and_add
действительно атомарно, но ведет себя как обычная функция - поэтому он принимает текущее значение "num" в качестве параметра. Не совсем корректно говорить, что атомарность функции нарушена, потому что на нее отвечает пользователь, загружающий значение из num
, и он не является частью функционального интерфейса. Я мог бы также жаловаться на это:
__sync_fetch_and_add(&var, some_really_long_function());
Или хуже,
__sync_fetch_and_add(long_function_1(), long_function_2());
Вы говорите, что это "может быть истолковано как"
- Загрузите адрес переменной var
- Загрузите значение переменной num
- Выполнение добавления атома
Но, согласно спецификации C, это не значит, что это может быть интерпретировано таким образом, но, скорее, это должно интерпретироваться таким образом, иначе компилятор не будет соответствовать (на самом деле он мог бы заменить # 1 и # 2, но что здесь не важно).