Если нужно просто из цикла условно одновременно во ВСЕХ потоках выходить, то что разумней цикл по мутексу делать или по atomic_bool ??? или вообще это все работает одинаково и на атомике просто кода будет меньше
Оговорюсь С++20 недоступен, поэтому atomic_flag урезан.
Конструкция класса мутекса (заимствовано)
class multithr_off
{
private:
    using guard = unique_lock<mutex>;
    bool _on;
    mutable condition_variable cv;
    mutable mutex lock;
public:
    using ptr_t = shared_ptr<multithr_off>;
    multithr_off() : _on(true) {}
    bool isOn() const
    {
        guard g(lock);
        return _on;
    }
    void off()
    {
        guard g(lock);
        _on = false;
        g.unlock();
        cv.notify_all();
    }
};
auto poff = make_shared<multithr_off>();
Варианты проверок (все имеют тело цикла с обработкой)
1. ожидание вода с клавиатуры (вообще выходит отсюда по isOn!?)
 while ((c = getchar()) != EOF && poff->isOn())
2. ожидание семафора, который отпустят из другого потока
 while (sem_wait(psem) == 0 && poff->isOn())
3. ожидание сброса атомика из другого потока
 atomic_bool abRunRead(false);
 abRunRead.store(true);
 while (abRunRead.load() && poff->isOn())
Честно говоря даже не знаю - проверяются сразу оба условия или последовательно и, например, второе не проверяется если первое ложно.






