Для включения в C ++ 14 (он же C ++ 1y) предложены некоторые новые примитивы синхронизации потоков: защелки и барьеры. Предложение
Это звучит как хорошая идея, и сэмплы делают его очень удобным для программистов. К сожалению, я думаю, что пример кода вызывает неопределенное поведение. В предложении говорится о latch::~latch()
:
Уничтожает защелки. Если защелка разрушена, в то время как другие темы находятся в
wait()
или призываемcount_down()
, поведение не определено.
Обратите внимание, что это говорит «в wait()
«а не» заблокирован в wait()
«, как описание count_down()
использует.
Затем предоставляется следующий образец:
Пример второго варианта использования показан ниже. Нам нужно загрузить данные и затем обработать их, используя несколько потоков. Загрузка данных связана с вводом / выводом, тогда как запуск потоков и создание структур данных связаны с процессором. Запустив их параллельно, можно увеличить пропускную способность.
void DoWork() { latch start_latch(1); vector<thread*> workers; for (int i = 0; i < NTHREADS; ++i) { workers.push_back(new thread([&] { // Initialize data structures. This is CPU bound. ... start_latch.wait(); // perform work ... })); } // Load input data. This is I/O bound. ... // Threads can now start processing start_latch.count_down(); }
Разве нет условия гонки между нитями, просыпающимися и возвращающимися из wait()
, а разрушение защелки когда оно выходит за рамки? Кроме того, все thread
объекты просочились. Если планировщик не запускает все рабочие потоки раньше count_down
возвращается и start_latch
объект выходит из области видимости, тогда я думаю, что неопределенное поведение приведет к. Предположительно, решение состоит в том, чтобы перебрать вектор и join()
а также delete
все рабочие потоки после count_down
но прежде чем вернуться.
Примечание. Возможно, один или несколько рабочих потоков еще не начали ждать и поэтому будут вызывать wait()
на разрушенной защелке.
Обновление: появилась новая версия предложения, но типичный пример не изменился.
Спасибо за указание на это. Да, я думаю, что пример кода (который в его защиту должен был быть кратким) не работает. Вероятно, следует дождаться окончания потоков.
Любая реализация, которая позволяет блокировать потоки в wait (), почти наверняка будет включать в себя некоторую переменную условия, и уничтожение защелки, пока поток еще не вышел, wait () потенциально не определено.
Я не знаю, есть ли время обновить документ, но я могу убедиться, что следующая версия исправлена.
Алэсдэйр
Других решений пока нет …