EDIT
我通过在Shared结构中使用单个互斥变量而不是Unique中的多个互斥锁来解决我的问题。如果有人理解为什么这个有效而另一个人没有(可靠地),我会很乐意接受答案
编辑
我用c ++ 11线程编写了一个简单的线程池。在Windows上它的行为与预期相同,但在linux上它会阻止。我认为我编程错了,它只是巧合地在Windows上运行。
想法是创建一次池并多次调用run(),它在所有可用线程上运行一次程序,然后返回而不破坏线程。然后线程等待下一次运行,依此类推。
在Windows上,每次我尝试它都会有效。然而,在Linux上只有一个线程开始执行程序,之后没有任何反应,所以run()永远不会返回。
我已经包含了我的源代码的一个稍微浓缩的版本,因为我认为这个东西可能足够小。如果有人有兴趣看看我怀疑代码部分中间的loop()和wait_all()是最相关的部分。如果从名称/上下文中不清楚变量类型,我还将声明作为参考包含在内。
Pool::Pool(uint32_t num_threads) : num_threads_(num_threads), uniques_(num_threads), threads_(num_threads) {
shared_.end = false;
for (uint32_t i = 0; i < num_threads; ++i) {
uniques_[i].wake = false;
threads_[i] = std::thread(loop, std::ref(uniques_[i]), std::ref(shared_));
}
}
void Pool::run(Program program) {
shared_.program = program;
wake_all();
wait_all();
}
void Pool::wake_all() {
for (size_t i = 0; i < uniques_.size(); ++i) {
uniques_[i].wake = true;
}
shared_.wake_signal.notify_all();
}
void Pool::wait_all() {
for (size_t i = 0; i < num_threads_; ++i) {
std::unique_lock<std::mutex> locker(uniques_[i].lock);
uniques_[i].done_signal.wait(locker, [&]{return !uniques_[i].wake;});
}
}
void Pool::loop(Unique& unique, Shared& shared) {
for (;;) {
std::unique_lock<std::mutex> locker(unique.lock);
shared.wake_signal.wait(locker, [&]{return unique.wake;});
if (shared.end) {
break;
}
// Do stuff... On linux only a single thread gets here
shared.program();
unique.wake = false;
locker.unlock();
unique.done_signal.notify_all();
}
}
// Declaration
class Pool {
public:
typedef std::function<void()> Program;
Pool(uint32_t num_threads);
void run(Program program);
private:
void wake_all();
void wait_all();
struct Unique {
std::condition_variable done_signal;
std::mutex lock;
bool wake;
};
struct Shared {
Program program;
std::condition_variable wake_signal;
bool end;
};
uint32_t num_threads_;
Shared shared_;
std::vector<Unique> uniques_;
std::vector<std::thread> threads_;
static void loop(Unique& unique, Shared& shared);
};
答案 0 :(得分:0)
您违反了调用wait
的标准要求:
void wait(unique_lock&amp; lock);
要求:lock.owns_lock()为true且lock.mutex()被调用线程锁定,并且:或者
- 没有其他线程在等于这个condition_variable对象或
- lock.mutex()为所有并发等待(通过wait或timed_wait)线程提供的每个锁参数返回相同的值。
您可以同时等待lock
引用不同mutex
的线程。因此,您无法满足在wait
上调用condition_variable
的先决条件。
我相信你可以使用condition_variable_any
,但没有这个要求。