Код: Выделить всё
#include
#include
#include
#include
#include
int main()
{
std::atomic flag = {false};
std::atomic val = {0};
std::thread t1([&](){
val.store(1,std::memory_order::relaxed); // #1
flag.store(true,std::memory_order::relaxed); // #2
});
std::thread t2([&](){
while(!flag.load(std::memory_order::relaxed)){} // #3
auto r = val.exchange(2,std::memory_order::relaxed); // #4
assert(r!=0); // #5
});
t1.join();
t2.join();
}
Атомарные операции чтения-изменения-записи всегда должны считывать последнее значение (в порядке модификации), записанное ранее запись, связанная с операцией чтения-изменения-записи.
Гарантированно ли, что #5 в этом примере не сработает? В этом примере утверждение не срабатывает https://godbolt.org/z/G8KzK3o8W
Обновление:
Код: Выделить всё
#include
#include
#include
#include
#include
int main()
{
std::atomic flag = {false};
std::atomic val = {0};
std::thread t1([&](){
val.store(1,std::memory_order::relaxed); // #1
val.exchange(2,std::memory_order::relaxed); //#2
flag.store(true,std::memory_order::relaxed); // #3
});
std::thread t2([&](){
while(!flag.load(std::memory_order::relaxed)){} // #4
// auto r = val.load(std::memory_order::relaxed);
auto r = val.exchange(3,std::memory_order::relaxed); // #5
});
t1.join();
t2.join();
}
Какие возможные значения #2 может возвращать в этом примере? он возвращает 1, сохраненный в #1, это интуитивно понятный случай. Может ли #2 прочитать значение 3, хранящееся в #5?
Q2:
Если # 2 читается как 1, означает ли это, что #5 должен читать 2, который хранится в #2, или это также может быть 0? В той же ситуации, если #5 — это чистая загрузка, как написано в комментарии, означает ли это, что результат может быть 0, 1 или 2?
Подробнее здесь: https://stackoverflow.com/questions/790 ... when-the-s