Являются Атомарными чтения C++ и Записи интервала?

У меня есть два потока, одно обновление интервала и одно чтение его. Это - статистическое значение, где порядок чтений и записей не важен.

Мой вопрос, я должен синхронизировать доступ к этому многобайтовому значению так или иначе? Или, помещенный иначе, может отделиться записи быть завершенным и быть прерванными, и затем чтение происходит.

Например, думайте о значении = 0x0000FFFF, который получает увеличенное значение 0x00010000.

Существует ли время, где значение похоже на 0x0001FFFF, по поводу которого я должен быть взволнован? Конечно, чем больше тип, тем более возможный что-то вроде этого для случая.

Я всегда синхронизировал эти типы доступов, но было любопытно, что думает сообщество.

79
задан Kirill Kobelev 7 February 2017 в 05:59
поделиться

13 ответов

В сначала можно было бы думать, что чтения и записи собственного размера машины являются атомарными, но существует много проблем для контакта с включением когерентности кэш-памяти между процессорами/ядрами. Атомарным операциям использования нравится, Взаимно блокировался* в Windows и эквиваленте на Linux. C++ 0x будет иметь "атомарный" шаблон для обертывания их в хороший и межплатформенный интерфейс. На данный момент при использовании уровня абстракции платформы, он может обеспечить эти функции. ACE делает, видит шаблон класса ACE_Atomic_Op .

47
ответ дан Adam Mitz 24 November 2019 в 10:15
поделиться

Asside от проблемы кэша упомянул выше...

при портировании кода на процессор с меньшим размером регистра это больше не будет атомарным.

IMO, распараллеливающие проблемы являются слишком тернистыми для риска им.

0
ответ дан JeffV 24 November 2019 в 10:15
поделиться

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

0
ответ дан Community 24 November 2019 в 10:15
поделиться

Для повторения, что все сказали наверху ПредC++ языка 0x ничего не может гарантировать о доступе общей памяти от нескольких потоков. Любые гарантии были бы до компилятора.

1
ответ дан Tim Cooper 24 November 2019 в 10:15
поделиться

В Windows Добавляет Взаимно блокируемый *** Exchange ***, как, гарантируют, будет атомарным.

3
ответ дан Andrew Stein 24 November 2019 в 10:15
поделиться

Необходимо синхронизироваться, но на определенной архитектуре существуют эффективные способы сделать это.

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

ядро Linux уже имеет часть этого кода.

3
ответ дан Jason Cohen 24 November 2019 в 10:15
поделиться

ЕСЛИ Вы читаете/пишете 4-байтовое значение, И оно DWORD-выравнивается в памяти, И Вы работаете на архитектуре I32, ТО чтения и записи являются атомарными.

11
ответ дан gabr 24 November 2019 в 10:15
поделиться

Да, необходимо синхронизировать доступы. В C++ 0x это будет гонка данных и неопределенное поведение. С потоками POSIX это уже - неопределенное поведение.

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

8
ответ дан Anthony Williams 24 November 2019 в 10:15
поделиться

Нет, они не (или по крайней мере Вы не можете предположить, что они). Однако существуют некоторые приемы, чтобы сделать это атомарно, но они обычно не являются портативными (см. Сравнивать-и-подкачивать ).

0
ответ дан Leon Timmermans 24 November 2019 в 10:15
поделиться

Мальчик, какой вопрос. Ответ, к которому:

Да, нет, хм, ну, в общем, это зависит

, Все это сводится к архитектуре системы. На IA32 правильно выровненный адрес будет атомарной операцией. Невыровненные записи могли бы быть атомарными, это зависит от кэширующейся используемой системы. Если память находится в единственной строке кэша L1 тогда, это является атомарным, иначе это не. Ширина шины между ЦП и RAM может влиять на атомарную природу: правильно выровненная запись на 16 битов на 8086 была атомарной, тогда как та же запись на 8088 не была то, потому что 8088 только имели шину на 8 битов, тогда как эти 8086 имели шину на 16 битов.

кроме того, если Вы используете C/C++, не забывают отмечать общее значение как энергозависимое, иначе оптимизатор будет думать, что переменная никогда не обновляется в одном из Ваших потоков.

63
ответ дан ildjarn 24 November 2019 в 10:15
поделиться

Единственный переносимый способ - использовать тип sig_atomic_t, определенный в заголовке signal.h для вашего компилятора. В большинстве реализаций C и C++ это int. Затем объявите вашу переменную как "volatile sig_atomic_t."

.
-1
ответ дан 24 November 2019 в 10:15
поделиться

Рассмотрим этот пример

int x;
x++;
x=x+5;

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

Еще один пример,

x=5;

Опять же, чтобы понять, что именно здесь происходит, нужно разобрать код.

0
ответ дан 24 November 2019 в 10:15
поделиться

tc, Я думаю, что в тот момент, когда вы используете константу (например, 6), инструкция не будет выполнена за один машинный цикл. Попробуйте посмотреть набор команд для x+=6 по сравнению с x++

0
ответ дан 24 November 2019 в 10:15
поделиться
Другие вопросы по тегам:

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