Если в настоящее время у меня есть назначение int в потоке: messageBox [i] = 2, как мне сделать это назначение atomi c? В равной степени для теста чтения, например if (messageBox [i] == 2).
Вам почти никогда не нужно ничего делать. Почти в каждом случае данные, которыми ваши потоки обмениваются (или обмениваются данными), защищены от одновременного доступа с помощью таких вещей, как мьютексы, семафоры и тому подобное. Реализация базовых операций обеспечивает синхронизацию памяти.
Причиной такого атомизма является помощь в построении более безопасных условий гонки в вашем коде. Есть ряд опасностей с ними; в том числе:
ai + = 7;
будет использовать протокол atomi c, если ai определено надлежащим образом. Попытка расшифровать условия гонки не помогает скрыть реализацию.
В них есть также сильно машинно-зависимая часть. Например, строка выше может давать сбой [1] на некоторых платформах, но как этот сбой сообщается программе? Это не [2].
Только одна операция имеет возможность справиться с ошибкой; atomic_compare_exchange_ (слабый | сильный). Слабый просто пытается один раз, и позволяет программе выбрать, как и следует ли повторить попытку. Сильные повторы бесконечно. Недостаточно просто попробовать один раз - возможны ложные сбои из-за прерываний, - но бесполезные повторные попытки при не поддельных сбоях также не годятся.
Возможно, для надежных программ или широко применимых библиотек, единственное, что вы должны использовать, это atomic_compare_exchange_weak ().
[1] Связанное с нагрузкой, условное хранилище (ll-s c) является распространенным средством для выполнения транзакций atomi c на асинхронной шине архитектуры. Связанный с нагрузкой устанавливает небольшой флажок в строке кэша, который будет очищен, если какой-либо другой агент шины попытается изменить эту строку кэша. Условное хранилище хранит значение, если в кэше установлен маленький флаг, и очищает флаг; если флаг сброшен, условное хранилище сообщает об ошибке, поэтому можно попытаться выполнить соответствующую операцию повтора. Из этих двух операций вы можете создать любую операцию atomi c, которая вам нравится на полностью асинхронной архитектуре шины.
ll-s c может иметь тонкие зависимости от атрибутов кэширования Местоположение. Допустимые атрибуты кэша зависят от платформы, как и то, какие операции могут выполняться между ll и s c.
Если вы поставили операцию ll-s c на плохо кэшированный доступ и слепо повторите попытку, ваша программа заблокируется. Это не просто предположение; Мне пришлось отлаживать один из них в «безопасной» системе на основе ARMv7.
[2]:
#include <stdatomic.h>
int f(atomic_int *x) {
return (*x)++;
}
f:
dmb ish
.L2:
ldrex r3, [r0]
adds r2, r3, #1
strex r1, r2, [r0]
cmp r1, #0
bne .L2 /* note the retry loop */
dmb ish
mov r0, r3
bx lr