我有以下时序代码,似乎没有按需要等待条件变量。目标是生成所有线程,然后让它们全部同时开始工作。
过早似乎被称为。有什么想法吗?
chrono::milliseconds timeNThreadsLockFree(int n, int worksize)
{
boost::lockfree::stack<int> data(totalNumberOfWorkItems);
vector<thread> ts;
atomic<int> count;
condition_variable cv;
mutex mut2;
unique_lock<mutex> ul(mut2,defer_lock);
lock(ul,mut);
auto startSpawn = chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
ts.push_back(thread([&](){
cv.wait(ul, [](){return true; });
int q = 5;
for (int j = 0; j < worksize; j++){
data.push(7);
else count++;}
}));
if (count != 0) {
cout << "premature" << endl; }
cv.notify_all();
auto startWait = chrono::high_resolution_clock::now();
for (auto&& t : ts)
t.join();
auto endWait = chrono::high_resolution_clock::now();
if (count != totalNumberOfWorkItems)
cout << "not done" << endl;
return chrono::duration_cast<chrono::milliseconds>(endWait - startWait);
}
答案 0 :(得分:0)
我认为问题在于cv.wait
调用的第二个参数。 cppreference表示在发生虚假唤醒时调用的谓词的第二个参数,并且:
谓词如果等待应该继续,则返回false
因此,为了确保锁定确实有效,你应该在main函数中创建一个像ready
这样的变量,然后在等待中使用它:
bool ready = false;
...
cv.wait(ul, [](){ return ready; });
...
ready = true;
cv.notify_all();
另外,您可能想尝试为每个线程单独std::unique_lock
,而不是重新使用main函数中的那个:
ts.push_back(thread([&]() {
std::unique_lock<std::mutex> ul2(mut2);
cv.wait(ul2, [](){ return ready; });
然后,您还需要解锁main函数中的旧锁:
ready = true;
ul.ulock();
cv.notify_all();
最后,由于您希望所有线程同时运行,您可能希望手动解锁内部std::unique_lock
以便运行多个线程:
ts.push_back(thread([&]() {
std::unique_lock<std::mutex> ul2(mut2);
cv.wait(ul2, [](){ return ready; });
ul2.unlock();
答案 1 :(得分:0)
在整个地方进行一堆锁定/解锁/等待/通知通常是您使用错误工具的线索。使用boost::barrier
(或自己动手,实现起来很简单):
boost::barrier bar(n+1);
for (int i = 0; i < n; i++)
ts.push_back(thread([&](){
bar.wait();
// ...
}));
// ...
bar.wait(); // after this line all threads will be released from the barrier