У меня есть реализация пула потоков, которая останавливает все потоки, устанавливая специальную атомную лобку Stop true. Его деструктор выглядит так: < /p>
Код: Выделить всё
ThreadPool::~ThreadPool()
{
stop.store(true);
for (std::thread& worker : workers)
{
worker.join();
}
}
Если я правильно понимаю стандарт, memory_order_seq_cst хранить гарантирует только барьер выпуска. И я не нашел такую информацию о std :: think :: join , но поток заканчивается синхронизируется с join , так что это своего рода операция приобретения. Если это правда, то я не вижу причины, по которой это переупорядочение невозможно: < /p>
Код: Выделить всё
ThreadPool::~ThreadPool()
{
for (std::thread& worker : workers)
{
worker.join();
}
stop.store(true);
}
< /code>
Это приведет к тупику. Он передает ared_future
GO_READY во все созданные потоки, чтобы предотвратить ситуацию, когда первый поток уже закончен к тому времени, когда мы создаем второй. Каждый поток создан с помощью std :: async , поэтому он возвращает будущее, скажем, thread_ready .
Основной поток делает что-то вроде этого:
Код: Выделить всё
// Start the threads
go.set_value();
thread_ready.get();
< /code>
Переупорядочение этих 2 выражений также приведет к тупику. И кажется, что set_value ()
выпуск и get () приобретает, поэтому ничто не мешает им переупорядочить, по крайней мере, в моем понимании.
Так безопасно?
Подробнее здесь:
https://stackoverflow.com/questions/797 ... reordering