2015-05-30 2 views
0

У меня есть неатомный 62-битный двойной, который регулярно увеличивается в одном потоке. Этот доступ не обязательно должен быть атомарным. Однако эта переменная иногда читается (не написана) другим потоком. Если я выровняю переменную на 64-битной границе, чтение будет атомарным.Прочитать неатомную переменную атомарно?

Однако, есть ли способ, которым я могу убедиться, что я не читаю переменную в середине приращения? Могу ли я вызвать инструкцию CPU, которая сериализует конвейер или что-то еще? Память барьер?

Я думал об объявлении переменной атома и используя std::memory_order::memory_order_relaxed в моей критической ветке (и более строгий барьер памяти в редкой ветке), но, похоже, это так же дорого.

+1

Используйте '' удобства. Все остальное приводит к неопределенному поведению. Если вы * знаете, что согласованные 64-битные чтения являются атомарными, то вы, вероятно, можете доверять своему компилятору и знать об этом. –

+1

@ Kerrek SB: вы правы (несмотря на то, что библиотечные писатели заведомо плохи с многопоточным движением, они, наконец, догоняют). Однако при использовании нужно понимать, что происходит «под капотом», или удар производительности может быть огромным. Ответ harold можно рассматривать как объяснение _why_ некоторые вещи быстрее при использовании атомистики (например, я ожидаю, что из-за этого хорошая реализация на многих платформах заставит store (load() + 1) порядок больше, чем атомный приращение, хотя он, безусловно, имеет разную семантику и не всегда уместен). –

ответ

3

Поскольку вы отметили x86, это будет x86-специфическим.

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

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

+0

Справа. Более того, большинство других платформ (по крайней мере, те, которые соответствуют моделям памяти RMO, PSO и TSO, а также все одноядерные процессоры с одним гнездом/MCU) обладают таким свойством некоторых типов чтения и записи, внутренне-атомное-обеспеченное-правильное выравнивание (единственное различие - максимальный размер операнда, который является атомарным). Power и ARM _might_ будут исключением. –

+0

Вот что я сделал. До тех пор, пока я выровняю двойную до 64 бит, ее чтение должно быть атомарным. – user997112

Смежные вопросы