Возможно ли, что утверждение может завершиться неудачно с помощью Memory_order::relaxed для передачи указателей?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Возможно ли, что утверждение может завершиться неудачно с помощью Memory_order::relaxed для передачи указателей?

Сообщение Anonymous »

Рассмотрим этот пример:

Код: Выделить всё

#include 
#include 
#include 
#include 

int main(){
std::atomic val = 1;
std::atomic ptr = nullptr;
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
/*
if(r){
val_ptr->store(1,std::memory_order::release);
} // #6
*/
assert(r==false);  // #5
});
t1.join();
t2.join();
}
Может ли утверждение №5 никогда не давать сбой, даже если №1 и №2/ использовать смягченный порядок?
Утверждение не выполняется, только если #4 возвращает true. Это означает, что #4 выполнена успешно, то есть операция RMW загружает 1 и записывает -1. Модификация, значение которой равно 1, является только начальным значением атомарного объекта val.
В этой программе все операции над атомарным объектом val являются либо операциями RMW, либо чистыми загрузками (т. е. сбоями CAS). Таким образом, все эти операции сериализуются в соответствии с [atomics.order] p10:

Атомарные операции чтения-изменения-записи всегда должны считывать последнее значение (в порядке модификации), записанное перед записью, связанной с операцией чтения-изменения-записи.

То есть никакие две операции RMW не могут прочитать одну и ту же модификацию. Если #4 считывает начальное значение, то операции CAS не должны завершиться успешно, и это просто чистая загрузка.
Не уверен, что следующий анализ является формальным:
  • CAS в t1 не будет достигнут, если v равен -1, что приводит к тому, что цикл не завершается.
  • Ошибки CAS приводят к тому, что цикл не завершается, что приводит к его завершению. вернемся к приведенному выше условию.
  • Цикл завершится только в том случае, если CAS загрузит 1 и запишет 2 в этой программе.
Однако предполагается, что #4 загружает 1 и записывает -1. Если это произойдет, то цикл в t1 не сможет выйти, что означает, что #1 не может быть достигнут.
Цикл в t2 не может выйти, если загрузка читает nullptr. Таким образом, #5 может быть достигнут только в том случае, если цикл в t2 существует, что требует наличия некоторого побочного эффекта, отличного от нуля. В этой программе побочный эффект создания ненулевого указателя может быть только #1. Но согласно приведенному выше предположению #1 никогда не достигается. Следовательно, этот побочный эффект не может существовать где-либо в течение жизни программы.
Таким образом, #2 и #3 не могут прочитать значение, записанное в #1, иначе это нарушит [intro.races] p10:

Значение атомарного объекта M, определенное оценкой B, представляет собой значение, сохраненное некоторым неуказанным побочным эффектом A, который изменяет M, где B не происходит раньше О.

Итак, утверждение никогда не может потерпеть неудачу. Верен ли мой анализ?
Обновление:
Как будет вести себя утверждение при введении прокомментированного #6? IICU, если #5 завершается неудачно, цикл в t1 может завершиться только тогда, когда CAS прочитает значение, записанное #6; однако при этом выполнении #6 будет синхронизироваться с CAS в момент t1, что означает, что #2 не сможет прочитать #1( происходит до #1), цикл в момент t2 также не может завершиться в этом предположении. Утверждение по-прежнему не может потерпеть неудачу, потому что оно не будет достигнуто, верно?
Если мы изменим порядок памяти в #6 на расслабленный, похоже, что утверждение может потерпеть неудачу? Кажется, OOTA, но технически это может произойти.

Подробнее здесь: https://stackoverflow.com/questions/798 ... to-transfe
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»