c++11 线程池在 windows 上工作 - 在 linux 上阻塞
c++11 thread pool works on windows - blocks on linux
编辑
我通过在 Shared 结构中使用单个互斥量变量而不是在 Unique 中使用多个互斥量来解决我的问题。如果有人理解为什么这有效而另一个不(可靠地)我会很乐意接受答案。
编辑
我用 C++11 线程写了一个简单的线程池。在 windows 上它按预期运行,但在 linux 上它会阻塞。我假设我把它编程错了,巧合的是 运行ning 在 windows 上。
想法是创建一次池并多次调用 运行(),这 运行 在所有可用线程上对程序执行一次,然后 returns 不会破坏线程。然后线程等待下一个 运行 等等。
在 windows 上,我每次尝试都有效。然而,在 linux 上只有一个线程开始执行程序,之后什么也没有发生,所以 运行() 永远不会 returns.
我已经包含了我的源代码的一个稍微浓缩的版本,因为我认为它可能足够小。如果有人有兴趣看一下,我怀疑代码部分中间的 loop() 和 wait_all() 是最相关的部分。我还将声明作为参考,以防 name/context.
中的变量类型不清楚
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);
};
您违反了调用 wait
:
的标准要求
void wait(unique_lock& lock);
Requires: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either:
— no other thread is waiting on this condition_variable object or
— lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait or timed_wait) threads.
您可以同时等待其 lock
引用不同 mutex
的线程。所以你不满足在 condition_variable
.
上调用 wait
的先决条件
我相信您可以使用没有此要求的 condition_variable_any
。
编辑
我通过在 Shared 结构中使用单个互斥量变量而不是在 Unique 中使用多个互斥量来解决我的问题。如果有人理解为什么这有效而另一个不(可靠地)我会很乐意接受答案。
编辑
我用 C++11 线程写了一个简单的线程池。在 windows 上它按预期运行,但在 linux 上它会阻塞。我假设我把它编程错了,巧合的是 运行ning 在 windows 上。
想法是创建一次池并多次调用 运行(),这 运行 在所有可用线程上对程序执行一次,然后 returns 不会破坏线程。然后线程等待下一个 运行 等等。
在 windows 上,我每次尝试都有效。然而,在 linux 上只有一个线程开始执行程序,之后什么也没有发生,所以 运行() 永远不会 returns.
我已经包含了我的源代码的一个稍微浓缩的版本,因为我认为它可能足够小。如果有人有兴趣看一下,我怀疑代码部分中间的 loop() 和 wait_all() 是最相关的部分。我还将声明作为参考,以防 name/context.
中的变量类型不清楚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);
};
您违反了调用 wait
:
void wait(unique_lock& lock);
Requires: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either:
— no other thread is waiting on this condition_variable object or
— lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait or timed_wait) threads.
您可以同时等待其 lock
引用不同 mutex
的线程。所以你不满足在 condition_variable
.
wait
的先决条件
我相信您可以使用没有此要求的 condition_variable_any
。