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

В C есть "i + = 1;" атомное?

В C, i+=1; atomic?

4b9b3361

Ответ 1

Стандарт C не определяет, является ли он атомарным или нет.

На практике вы никогда не пишете код, который терпит неудачу, если данная операция является атомарной, но вы вполне можете написать код, который терпит неудачу, если это не так. Предположим, что это не так.

Ответ 2

Нет.

Единственная операция, гарантируемая стандартом языка C как атомарная, заключается в назначении или извлечения значения/из переменной типа sig_atomic_t, определенной в <signal.h>.

(C99, глава 7.14 Обработка сигналов.)

Ответ 3

Определено в C, нет. На практике, может быть. Напишите его в сборке.

Стандарт не гарантирует никаких гарантий.

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

  • Не все машины даже имеют память инкремента op. Некоторым нужно загрузить и сохранить значение, чтобы работать на нем, поэтому ответ там "никогда".

  • На машинах, у которых есть opup memory op, нет уверенности, что компилятор не будет вызывать нагрузку, прирост и последовательность сохранения в любом случае или использовать какую-либо другую неатомную инструкцию.

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

  • На машинах, у которых есть атомарная память инкремента op, он может не указываться как часть архитектуры, а просто свойство конкретного выпуска чипа CPU или даже определенная основная логика или материнская плата конструкции.

Что касается "как это сделать атомарно", обычно есть способ сделать это быстро, а не прибегать к (более дорогому) согласованному взаимному исключению. Иногда это связано с особыми коллизионными повторяющимися кодовыми последовательностями. Лучше всего реализовать их в модуле языка ассемблера, так как он специфичен для конкретной цели, поэтому для HLL нет возможности переносимости.

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

Ответ 4

Является ли выражение атомарным или нет, зависит только от машинного кода, который генерирует компилятор, и архитектуры процессора, на которой он будет работать. Если добавление не может быть достигнуто в одной машинной инструкции, это вряд ли будет атомарным.

Если вы используете Windows, вы можете использовать функцию API InterlockedIncrement() для гарантированного атомного приращения. Существуют аналогичные функции для уменьшения и т.д.

Ответ 5

Это действительно зависит от вашей цели и мнемонического набора вашего UC/процессора. Если я - переменная, содержащаяся в регистре, то она может быть атомарной.

Ответ 6

Хотя я не могу быть атомарным для языка C, следует отметить, что он является атомарным на большинстве платформ. Документация библиотеки GNU C гласит:

На практике вы можете предположить, что int и другие целочисленные типы не больше, чем int являются атомарными. Вы также можете предположить, что типы указателей являются атомарными; это очень удобно. Оба эти предположения верны на всех машинах, поддерживаемых библиотекой GNU C, и на всех системах POSIX, о которых мы знаем.

Ответ 7

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

Ответ 8

Не обычно.

Если i - volatile, то это будет зависеть от вашего CPU architecure и компилятора - если добавление двух целых чисел в основной памяти является атомарным на вашем процессоре, тогда этот оператор C может быть атомарным с volatile int i.

Ответ 9

Сам язык C/С++ не претендует на атомарность или недостаток. Для обеспечения атомного поведения вам нужно полагаться на функции intrinsics или library.

Ответ 10

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

Ответ 11

Нет, стандарт C не гарантирует атомарность, и на практике операция не будет атомарной. Вы должны использовать библиотеку (например, Windows API) или встроенные функции компилятора (GCC, MSVC).

Ответ 12

Ответ на ваш вопрос зависит от того, является ли i локальной, static или глобальной переменной. Если i является static или глобальной переменной, то no, оператор i += 1 не является атомарным. Если, однако, i является локальной переменной, то оператор является атомарным для современных операционных систем, работающих на архитектуре x86 и, возможно, в других архитектурах. @Dan Cristoloveanu был на правильном пути для локального переменного случая, но есть и больше, что можно сказать.

(В дальнейшем я предполагаю современную операционную систему с защитой архитектуры x86 с потоковой реализацией, полностью реализованной с помощью переключение задач.)

Учитывая, что это код C, синтаксис i += 1 подразумевает, что i - это некоторая целочисленная переменная, значение которой, если оно является локальной переменной, хранится либо в регистре, например в %eax или в стеке. Сначала обработайте простой случай, если значение i хранится в регистре, скажем %eax, тогда компилятор C, скорее всего, переведет оператор на что-то вроде:

addl    $1, %eax

который, конечно, является атомарным, потому что ни один другой процесс/поток не должен иметь возможность изменять текущий регистр %eax, и сам поток не может изменить %eax снова, пока эта инструкция не завершится.

Если значение i хранится в стеке, это означает, что есть выборка памяти, приращение и фиксация. Что-то вроде:

movl    -16(%esp), %eax
addl    $1, %eax
movl    %eax, -16(%esp)  # this is the commit. It may actually come later if `i += 1` is part of a series of calculations involving `i`.

Обычно эта серия операций не является атомарной. Однако в современной операционной системе процессы/потоки не должны модифицировать другой стек потоков, поэтому эти операции выполняются без вмешательства других процессов. Таким образом, утверждение i += 1 также является атомарным.