下面的代码是我编写的一个结构,它允许我将工作排队以在多个工作线程上运行,它会阻塞主线程,直到有新的工作线程可用。
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
:
mu
设置时是否需要锁定互斥锁threadActive[index] = false
?编译器是否允许在设置
cond.notify_one()
之前threadActive[index] = false
重新排序代码并执行?
我认为当且仅当允许编译器重新排序语句时,才有必要锁定互斥锁。这个对吗?