Это гонка данных для доступа к общим данным после присоединения к потоку?

#c #multithreading

#c #многопоточность

Вопрос:

Приводит ли следующий код к гонке данных:

 int f()
{
    int i = 0;
    std::thread t{[amp;]{ i = 1; }};
    t.join();
    return i;
}
  

Для i доступа не используются мьютексы или атомы.

В документации std::thread::join говорится о «завершении синхронизации потока с соответствующим успешным возвратом из join()», но я не уверен, будет ли это уместно в данном контексте.

Комментарии:

1. После объединения остается только один поток — как может быть гонка?

2. Нет никаких обещаний, что обновление переменной будет видно. На практике это всегда работает, потому что низкоуровневая реализация join () не может работать без барьера памяти.

3. @HansPassant, да, видимость обновления была моей заботой здесь. Мне было интересно, является ли cppreference.com цитата в вопросе каким-то образом связана с этим. Приведенный ниже ответ Брайана предполагает, что это было бы.

Ответ №1:

Как говорится на связанной странице,

Завершение потока, обозначенного *this, синхронизируется с соответствующим успешным возвратом из join().

Это подразумевает, что все, что происходит в t перед t завершением работы (то есть все, что происходит в t ), происходит до того, как все, что происходит в основном потоке после t.join() возврата. Следовательно, запись в i внутри потока t происходит до i считывания оператором return . Следовательно, два доступа к i потенциально не являются одновременными. Следовательно, гонки данных нет.

Комментарии:

1. Найдена соответствующая стандартная цитата: «Вычисление A в значительной степени происходит перед вычислением B, если либо: A упорядочивается перед B, либо A синхронизируется с B …» [вступление.гонки]

Ответ №2:

Приводит ли следующий код к гонке данных

Нет. Правило заключается в том, что если у вас более одного потока, и хотя бы один из них является автором, вам нужна синхронизация при доступе к общим данным. Ключевым моментом здесь является более чем один поток. После вызова join у вас больше нет более одного потока, поэтому main доступ к i безопасен.