2

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

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), std::end(threadActive), true);
        };
        auto availableThread = [&](){
            return std::find(std::begin(threadActive), std::end(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);
    }
};

我对由 lambda 执行的代码有两个问题jthread

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

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

我认为当且仅当允许编译器重新排序语句时,才有必要锁定互斥锁。这个对吗?

4

0 回答 0