Код: Выделить всё
#include
#include
#include
#include
int main(){
std::atomic val = 1;
std::atomic ptr;
auto t1 = std::thread([&](){
auto v = val.load(std::memory_order::relaxed);
while(true){
if(v==-1){
v = val.load(std::memory_order::relaxed);
continue;
}
if(val.compare_exchange_strong(v,v+1,std::memory_order::acquire,std::memory_order::relaxed)==true){
break;
}
}
ptr.store(&val,std::memory_order::relaxed); // #1
});
auto t2 = std::thread([&ptr](){
std::atomic* val_ptr = ptr.load(std::memory_order::relaxed); // #2
while(val_ptr==nullptr){
val_ptr = ptr.load(std::memory_order::relaxed); // #3
}
int v = 1;
bool r = val_ptr->compare_exchange_strong(v,-1,std::memory_order::acquire,std::memory_order::relaxed); // #4
assert(r==false); // #5
});
t1.join();
t2.join();
}
Код: Выделить всё
#3Атомарные операции чтения-изменения-записи всегда должны считывать последнее значение (в порядке модификации), записанное перед записью, связанной с операцией чтения-изменения-записи.
То есть никакие две операции RMW не могут прочитать одну и ту же модификацию. Если #4 считывает начальное значение, то операции CAS не должны завершиться успешно, и это просто чистая загрузка. Не уверен, что следующий анализ является формальным:
- в t1 не будет достигнут, если v равен -1, что приводит к невозможности выхода из цикла
Код: Выделить всё
CAS - приводят к тому, что цикл не завершается, и возвращаемся к вышеизложенному
Код: Выделить всё
CASСбои
Значение атомарного объекта M, определенное оценкой B, представляет собой значение, сохраненное неким неуказанным побочным эффектом A, который модифицирует M, где B не происходит раньше A.
Таким образом, утверждение никогда не может потерпеть неудачу. Верен ли мой анализ?
Подробнее здесь: https://stackoverflow.com/questions/798 ... to-transfe
Мобильная версия