Где-то я читал, что унарные операторы атомарны по своей природе и поэтому их можно использовать в многопоточной среде. Чтобы подтвердить то же самое, я написал две отдельные программы, в которых
Сравнил разборку обеих программ и разницы не нашел. Пожалуйста, поделитесь своим мнением по этому поводу.
Учитывая, что переменная может находиться в памяти и, следовательно, требовать нескольких инструкций (загрузка, добавление, сохранение), они не являются атомарными автоматически.
Неважно, является ли какая-то инструкция атомарной, у вас либо правильная синхронизация, либо гонка.
Я подозреваю, что где бы вы ни читали, слово «атомарный» использовалось в другом смысле, чем в контексте параллелизма. Либо так, либо они были совершенно неправы, и не стоит доверять всему, что вы там видели.
std::atomic может быть реализован кем-то, кто знает оборудование, на которое вы нацеливаетесь, возможно, намного лучше, чем вы. Пусть за работу сделает эксперт. Используйте std::atomic, когда вам нужна атомарность.
В C ++ до / после исправления не являются унарные операторы, например & * + - ~ !. но часть унарное выражение. Таким образом, заголовок вопроса не соответствует тексту.
@chux В вопросе написано «унарный оператор», а не «унарный оператор» с дефисом и курсивом, что подразумевает специфическое для грамматики C / C++ значение. Postfix operator++ также не является частью унарное выражение, но постфиксное выражение. Унарный оператор - это общий, широко понимаемый термин, который здесь правильно используется.
@palotasb постфиксное выражение - это одна из форм унарное выражение. Верно, я использую указанное в C значение, поскольку это объективно. по сравнению с более широко понимаемым термином, который может иметь различные толкования. В конце концов, OP ищет конкретный ответ для C / C++, а не для общего программирования.





Somewhere I read that unary operators are atomic by nature and so they can be used as it is in multi threaded environment.
Этот источник совершенно неверен. Вам нужно использовать std::atomic (или эквивалент C) для достижения атомарности - унарные операции не являются чем-то особенным.
I compared the disassembly of both programs and found no difference
Это не означает, что сгенерированные операции атомарны. Нет никакой разницы, поскольку любой достойный компилятор оптимизирует x=x+1 и ++x в одну и ту же сборку (при условии встроенных типов).
Сравнение сборки может подтвердить обратное. Если вы знаете, что сборка i = i + 1 неатомарна, то эта же сборка неатомарна для i++, следовательно, последняя не является атомарной.
Утверждение, что унарный оператор обязательно атомарен, является мифом.
Например, для ++x требуется чтение и запись в x, что открывает возможность гонки данных.
Тот факт, что ++x компилируется с тем же кодом, что и x = x + 1, не имеет значения.
Если вы хотите избежать гонки данных, используйте атомарные типы или единицы взаимного исключения, если соответствующий атомарный тип недоступен. Во избежание сомнений, int не обязательно является атомарным типом.
Somewhere I read that unary operators are atomic by nature and so they can be used as it is in multi threaded environment.
Это неправда. x++, например, требует загрузки x, добавления и сохранения x. Эти инструкции не атомарны по своей природе.
Не правда. Даже если бы это было так, какая тогда причина была бы в https://en.cppreference.com/w/cpp/atomic/atomic#Type_aliases?
Я думаю, что они, вероятно, имели в виду, что вычисление такой операции обычно очень незначительное и, следовательно, с высокой вероятностью никогда не будет состояния гонки, что в основном верно для живого кода, где вы не вычисляете x ++ в 4 циклах одновременно.
Атомарность операции stronglr зависит от целевой системы. Унарная операция может не быть атомарной в системах RMW, таких как микроконтроллеры RISC.
На этот вопрос нет единого универсального ответа.
Хороший ответ (хотя и немного краткий), поскольку он не утверждает, что он никогда не может быть атомарным (как это делают другие). Но: есть «единственный общий ответ» на вопрос: «Нет, унарные операторы нет являются атомарными по природе».
@Ctx это зависит от уровня абстракции. Если абстрагироваться от реализации и железа - да. Если нет - нет.
@P__J__ Язык C определен в терминах абстрактной машины: «Семантические описания в этом международном стандарте описывают поведение абстрактной машины, в которой вопросы оптимизации не имеют значения». Единственный общий ответ является «унарные операторы не атомарны».
@AndrewHenle, вы правы - но в практике программирования многие программисты (особенно те, кто очень близок к оборудованию) должны учитывать реализацию и оборудование. Простой пример - что делать, если у вас есть критичная по времени функция, и вы не можете отключить прерывания? stdatomic в этом случае не поможет.
При написании кросс-платформенного C++ у вас есть только атомарное поведение при использовании std::atomic<>.
Это правда, что на некоторых платформах, таких как Intel 64bit, процессор гарантирует, что inc является атомарным. Однако, пожалуйста, не пишите код, который зависит от этого! Как ваш будущий отладчик, я хотел бы знать, какие данные предназначены для совместного использования по потокам, а какие нет.
Использование std::atomic<int> может потребовать немного больше работы для написания, однако оно гарантирует, что все будет вести себя атомарно (на каждой платформе) либо путем возврата к требованиям платформы (std :: atomic :: is_lock_free), либо путем явной блокировки доступа. Он также вставляет ограждения, чтобы убедиться, что кеши других ядер процессора недействительны (если этого требует платформа).
На практике для Intel 64bit это должно дать вам ту же сборку, если нет, зарегистрировать ошибку в вашем компиляторе.
В то же время некоторые операции с целыми числами могут не быть атомарными (оператор * =), std::atomic просто не хранит эти операции, требуя от вас правильной работы с ними.
Кстати, ++x и x = x+1 - это разные операции, они могут быть оптимизированы для одной и той же сборки. Учитывая неатомарные требования к платформе, вторая внезапно представляет собой ошибку, на решение которой уходит несколько дней.
Вы делаете предположение о сгенерированном коде, если сгенерирована только одна инструкция, да, она будет атомарной, иначе нет.
В вашем случае это предполагает, что целевой процессор имеет инструкцию inc <address>, и компилятор сгенерирует ее.
Вы не указали тип x.
«операция определенно будет выполнять несколько операций» - я бы не стал делать это утверждение. У вас могут быть 32-битные регистры на 16-битных архитектурах, и вам нужна только блокировка шины, за которой следует приращение, чтобы x ++ был атомарным.
Я согласен с вами, что это будет зависеть от обрабатываемого объекта. Для упрощения я использовал целое число 32 бита. Но мне следовало использовать 64-битное целое число, так как моя машина 64-битная, поэтому ОС (Windows 10)
Atomic behavior of unary operators
В C ++ до / после исправления не являются унарные операторы, например & * + - ~ !. но часть унарное выражение. Таким образом, заголовок вопроса не соответствует тексту.
Даже унарный оператор, такой как +, не является атомарным, поскольку доступ к объекту (например, long long) заставляет выполнять несколько операций чтения кода операции.
То, что
++xатомарен, не означает, чтоx=x+1нет? (С логической точки зрения я сомневаюсь, что++xи так всегда атомарен)