Операция на самом деле является двумя операциями.
__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, но это не важно).