У меня есть два потока, одно обновление интервала и одно чтение его. Это - статистическое значение, где порядок чтений и записей не важен.
Мой вопрос, я должен синхронизировать доступ к этому многобайтовому значению так или иначе? Или, помещенный иначе, может отделиться записи быть завершенным и быть прерванными, и затем чтение происходит.
Например, думайте о значении = 0x0000FFFF, который получает увеличенное значение 0x00010000.
Существует ли время, где значение похоже на 0x0001FFFF, по поводу которого я должен быть взволнован? Конечно, чем больше тип, тем более возможный что-то вроде этого для случая.
Я всегда синхронизировал эти типы доступов, но было любопытно, что думает сообщество.
В сначала можно было бы думать, что чтения и записи собственного размера машины являются атомарными, но существует много проблем для контакта с включением когерентности кэш-памяти между процессорами/ядрами. Атомарным операциям использования нравится, Взаимно блокировался* в Windows и эквиваленте на Linux. C++ 0x будет иметь "атомарный" шаблон для обертывания их в хороший и межплатформенный интерфейс. На данный момент при использовании уровня абстракции платформы, он может обеспечить эти функции. ACE делает, видит шаблон класса ACE_Atomic_Op .
Asside от проблемы кэша упомянул выше...
при портировании кода на процессор с меньшим размером регистра это больше не будет атомарным.
IMO, распараллеливающие проблемы являются слишком тернистыми для риска им.
Я соглашаюсь со многими и особенно Jason. На окнах можно было бы, вероятно, использовать InterlockedAdd и его друзей.
Для повторения, что все сказали наверху ПредC++ языка 0x ничего не может гарантировать о доступе общей памяти от нескольких потоков. Любые гарантии были бы до компилятора.
В Windows Добавляет Взаимно блокируемый *** Exchange ***, как, гарантируют, будет атомарным.
Необходимо синхронизироваться, но на определенной архитектуре существуют эффективные способы сделать это.
Лучший должен использовать подпрограммы (возможно, замаскированный позади макросов) так, чтобы можно было условно заменить реализации определенными для платформы.
ядро Linux уже имеет часть этого кода.
ЕСЛИ Вы читаете/пишете 4-байтовое значение, И оно DWORD-выравнивается в памяти, И Вы работаете на архитектуре I32, ТО чтения и записи являются атомарными.
Да, необходимо синхронизировать доступы. В C++ 0x это будет гонка данных и неопределенное поведение. С потоками POSIX это уже - неопределенное поведение.
На практике, Вы могли бы получить плохие значения, если тип данных больше, чем собственный размер слова. Кроме того, другой поток никогда не мог бы видеть значение, записанное из-за оптимизации, перемещающей чтение и/или запись.
Нет, они не (или по крайней мере Вы не можете предположить, что они). Однако существуют некоторые приемы, чтобы сделать это атомарно, но они обычно не являются портативными (см. Сравнивать-и-подкачивать ).
Мальчик, какой вопрос. Ответ, к которому:
Да, нет, хм, ну, в общем, это зависит
, Все это сводится к архитектуре системы. На IA32 правильно выровненный адрес будет атомарной операцией. Невыровненные записи могли бы быть атомарными, это зависит от кэширующейся используемой системы. Если память находится в единственной строке кэша L1 тогда, это является атомарным, иначе это не. Ширина шины между ЦП и RAM может влиять на атомарную природу: правильно выровненная запись на 16 битов на 8086 была атомарной, тогда как та же запись на 8088 не была то, потому что 8088 только имели шину на 8 битов, тогда как эти 8086 имели шину на 16 битов.
кроме того, если Вы используете C/C++, не забывают отмечать общее значение как энергозависимое, иначе оптимизатор будет думать, что переменная никогда не обновляется в одном из Ваших потоков.
Единственный переносимый способ - использовать тип sig_atomic_t, определенный в заголовке signal.h для вашего компилятора. В большинстве реализаций C и C++ это int. Затем объявите вашу переменную как "volatile sig_atomic_t."
.Рассмотрим этот пример
int x;
x++;
x=x+5;
Предполагается, что первое утверждение является атомарным, поскольку оно преобразуется в одну директиву сборки INC, которая занимает один цикл процессора. Однако второе присваивание требует нескольких операций, так что это явно не атомарная операция.
Еще один пример,
x=5;
Опять же, чтобы понять, что именно здесь происходит, нужно разобрать код.
tc, Я думаю, что в тот момент, когда вы используете константу (например, 6), инструкция не будет выполнена за один машинный цикл. Попробуйте посмотреть набор команд для x+=6 по сравнению с x++