#c #multithreading #c 20 #race-condition #barrier
Вопрос:
Рассмотрим следующий код на C :
#include <barrier>
#include <iostream>
#include <string>
#include <thread>
int main()
{
constexpr unsigned N = 2;
std::barrier barrier(N);
auto const run = [amp;barrier]()
{
std::string buff;
for(unsigned i = 0; i < 1000; i )
{
std::cout << ((buff = "A ") std::to_string(i) "n");
barrier.arrive_and_wait();
std::cout << ((buff = "B ") std::to_string(i) "n");
barrier.arrive_and_wait();
std::cout << ((buff = "C ") std::to_string(i) "n");
}
};
std::thread ts[N];
for(unsigned j = 0; j < N; j ) ts[j] = std::thread(run);
for(unsigned j = 0; j < N; j ) ts[j].join();
}
Когда я компилирую/запускаю его Clang 12.0.1
, он ведет себя так, как ожидалось.
Такое же ожидаемое поведение, когда я использую GCC 11.1 (C 20)
доступные онлайн по адресу en.cppreference.com.
Однако, когда я использую свой локальный , он часто блокируется после печати следующих строк GCC 11.1.0
:
A 0
A 0
B 0
B 0
C 0
A 1
- Является ли этот код четко определенным?
- Предполагается ли, что это не приведет к тупику?
Комментарии:
1. @463035818_is_not_a_number Я думаю, что OP означает Coliru, который используют кнопки «Запустить этот код» в cppreference.
2. Идея попытаться найти проблему: используйте
osyncstream
вместо записи непосредственно вstd::cout
и добавьте функцию завершения вstd::barrier
. Возможно, это покажет что-то интересное. Приготовил его здесь :3. Коша: Моя версия вашей программы также зависала, когда вы пробовали ее с вашим локальным GCC 11.1.0?
4. @TedLyngmo Я несколько раз пробовал это с помощью GCC 11.1.0. Он не генерировал никаких выходных данных (Ctrl C примерно через 10 секунд бездействия). Попытался скомпилировать его с помощью Clang, но
syncstream
файл не был найден.5. @Koosha Хорошо, возможно, версия clang слишком старая. Я получаю первую ошибку с clang 12.0.0
<barrier>
, хотя нет<syncstream>
. С clang 12.0.1 программа работает нормально.