编译器是否允许围绕 `std::condition_variable::notify_one` 重新排序语句?

问题描述

以下代码是我编写的一个结构体,它允许我将工作排队以在多个工作线程上运行,并且它会阻塞主线程,直到有新的工作线程可用。

struct WorkQueue{
    const std::size_t size;
    std::vector<uint8_t> threadActive;
    std::condition_variable cond;
    std::mutex mu;

    std::vector<std::jthread> threads;

    WorkQueue(std::size_t size_ = 1) :
        size{size_}
    {
        threads.resize(size);
        threadActive.resize(size);
        std::fill(std::begin(threadActive),std::end(threadActive),false);
    }

    template<typename Function>
    void enqueue(Function&& f){
        auto numActiveThreads = [&](){
            return std::count(std::begin(threadActive),true);
        };
        auto availableThread = [&](){
            return std::find(std::begin(threadActive),false) - std::begin(threadActive);
        };

        std::unique_lock<std::mutex> lock{mu};

        //wait until a thread becomes available
        if(numActiveThreads() == size){
            cond.wait(lock,[&](){ return numActiveThreads() != size; });
        }

        //get an available thread and mark it as active
        auto index = availableThread();
        threadActive[index] = true;

        //start the new thread and swap it into place
        std::jthread thread{[this,index,fn = std::forward<Function>(f)](){
            fn();
            threadActive[index] = false;
            cond.notify_one();
        }};
        threads[index].swap(thread);
    }
};

我有两个关于 jthread 执行的 lambda 代码的问题:

  1. 设置mu时是否需要锁定互斥量threadActive[index] = false

  2. 是否允许编译器重新排序代码并在设置 cond.notify_one() 之前执行 threadActive[index] = false

我认为当且仅当允许编译器对语句重新排序时,才需要锁定互斥锁。这是正确的吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)