В C “я + = 1”; атомарный?

Если у кого-либо есть копия Чтение кода Diomidis Spinellis, о каких проектах с открытым исходным кодом он пишет там?

@Avinash: Если бы Вы хотите узнать больше о программировании в целом, я рекомендовал бы и Качество Чтения кода и Кода Spinellis. У них есть примеры кода из различных проектов, всего FOSS, я верю, таким образом, можно не только читать о них, но идти и обсуждать версию в книге и последней версии, чтобы считать больше кода от них и учиться.

35
задан unwind 24 November 2009 в 13:54
поделиться

12 ответов

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

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

93
ответ дан 27 November 2019 в 06:24
поделиться

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

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

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

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

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

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

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

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

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

13
ответ дан 27 November 2019 в 06:24
поделиться

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

1
ответ дан 27 November 2019 в 06:24
поделиться

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

2
ответ дан 27 November 2019 в 06:24
поделиться

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

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

4
ответ дан 27 November 2019 в 06:24
поделиться

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

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

2
ответ дан 27 November 2019 в 06:24
поделиться

Нет.

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

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

20
ответ дан 27 November 2019 в 06:24
поделиться

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

1
ответ дан 27 November 2019 в 06:24
поделиться

Обычно нет.

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

1
ответ дан 27 November 2019 в 06:24
поделиться

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

1
ответ дан 27 November 2019 в 06:24
поделиться

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

1
ответ дан 27 November 2019 в 06:24
поделиться

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

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

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

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`.

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

1
ответ дан 27 November 2019 в 06:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: