編輯
我通過在Shared結構中使用單個互斥變量而不是Unique中的多個互斥體來解決我的問題。如果有人明白爲什麼這個工作,而另一個不(可靠),我會很樂意接受答案。
編輯C++ 11線程池在windows上運行 - linux上的塊
我寫了一個簡單的線程池與c + + 11線程。在Windows上它的行爲像預期的那樣,但是在Linux上它會阻塞。我假設我編寫了錯誤的代碼,它只是在巧合的窗口上運行。
想法是創建一次池並且多次調用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);
};
你的謂詞倒退在'wait_all'中。你想等待喚醒爲真,而不是假。此外,'wake_all'函數修改共享狀態('喚醒'布爾值),而不需要保持保護該狀態的鎖。 –
「共享」和「唯一」類型對我來說似乎沒有任何意義。 'Shared'在條件變量旁邊缺少一個互斥。你有沒有在死鎖狀態下調試你的代碼? – Yakk
@DavidSchwartz:wait_all中的顛倒謂詞是故意的。這可能有點不清楚,但想法是在wake_all中等待wake == true,在wait_all中等待wake == false。變量爲「喚醒我」和「我完成了」雙打。至少這是該計劃。 –