Код: Выделить всё
#include
#include
#include
int main() {
std::atomic strong = {3};
std::atomic weak = {1};
auto t1 = std::thread([&]() {
int expected = 1;
if (weak.compare_exchange_strong(expected, 255,
std::memory_order::acquire,
std::memory_order::relaxed) == true) {
bool unique = strong.load(std::memory_order::acquire) == 1;
weak.store(1, std::memory_order::relaxed);
assert(unique == false);
}
});
auto t2 = std::thread([&]() {
auto val = weak.load(std::memory_order::relaxed);
while (true) {
if (val == 255) {
std::this_thread::yield();
val = weak.load(std::memory_order::relaxed);
continue;
}
if (weak.compare_exchange_strong(
val, val + 1, std::memory_order::acquire,
std::memory_order::relaxed) == true) {
break;
}
}
strong.fetch_sub(1, std::memory_order::release);
});
auto t3 = std::thread([&]() {
auto val = weak.load(std::memory_order::relaxed);
while (true) {
if (val == 255) {
std::this_thread::yield();
val = weak.load(std::memory_order::relaxed);
continue;
}
if (weak.compare_exchange_strong(
val, val + 1, std::memory_order::acquire,
std::memory_order::relaxed) == true) {
break;
}
}
strong.fetch_sub(1, std::memory_order::release);
});
t1.join();
t2.join();
t3.join();
}
Если вычисление значения A атомарного объекта M происходит до операции B, которая изменяет M, то A берет свое значение из побочного эффекта X на M, где X предшествует B в порядке модификации M.
Код: Выделить всё
#1Значение атомарного объекта M, определенное оценкой B, представляет собой значение, сохраненное некоторым неуказанным побочным эффектом A, который изменяет M, где B не происходит раньше A.
Итак, #0 не может прочитать 1; однако он может читать 3 или 2. Верен ли мой анализ? На самом деле, это упрощенный вопрос, возникший в то время, когда я исследовал реализацию Arc в Rust, касающуюся is_unique и понижения версии, и я думаю, что порядок памяти, используемый для этого случая, является слишком строгим.
Подробнее здесь: https://stackoverflow.com/questions/798 ... p-in-other
Мобильная версия