[英]unique_lock across various threads
我有一个消费者和两个生产者。 当我同时产生两个生产者时,它们似乎互相锁定,因为我们看到的第一个值分别是223和889。
有人可以解释一下这里发生了什么吗?
#include<vector>
#include<thread>
#include<iostream>
#include<mutex>
#include<chrono>
#include <condition_variable>
using namespace std;
vector<double>testvec;
mutex mtx;
condition_variable cv;
class Base
{
public:
Base() {};
void dosomething();
int i;
};
void Base::dosomething()
{
while(1)
{
std::unique_lock<std::mutex> ulck(mtx);
testvec.push_back(i);
ulck.unlock();
cv.notify_all();
i++;
std::this_thread::sleep_for (std::chrono::milliseconds(i));
}
};
class Derived1 : public Base
{
public:
Derived1() {i = 222;}
};
class Derived2 : public Base
{
public:
Derived2() {i = 888;}
};
class Consumer
{
public:
Consumer() {}
void dostuff();
};
void Consumer::dostuff()
{
while(1)
{
std::unique_lock<std::mutex> ulck(mtx); //locks shared data
cv.wait(ulck);
cout<<"last value: "<<testvec.back()<<endl;
ulck.unlock();
}
}
int main( int argc, char ** argv )
{
Derived1 derived1;
Derived2 derived2;
Consumer c;
std::thread t1(&Derived1::dosomething, &derived1);
std::thread t2(&Derived2::dosomething, &derived2);
std::thread t3(&Consumer::dostuff, &c);
t1.join();
t2.join();
t3.join();
}
output is:
last value: 223
last value: 224
last value: 225
last value: 889
last value: 226
last value: 227
last value: 228
last value: 229
last value: 890
last value: 230
expected output:
last value: 888 (or 222)
last value: 222 (or 888)
last value: 223
...
没有谓词,您永远不会从wait
获得理智的行为。 另外,为什么只继续释放锁以立即再次锁定?
这是您要做的事情:
void Consumer::dostuff()
{
std::unique_lock<std::mutex> ulck(mtx); //locks shared data
int i = 0;
while(1)
{
// Correctly decide when to wait and when to stop waiting
while (testvec.empty() || (testvec.back() == i))
cv.wait(ulck);
i = testvec.back();
cout<<"last value: "<<testvec.back()<<endl;
}
}
条件变量是无状态的,没有办法知道它们应该等待还是何时停止等待,因为它们是共享状态的函数。 使用互斥锁保护共享状态是您的责任。
请注意,此代码仅在必须wait
时才调用wait。 您只能通过检查共享状态来判断是否需要等待。 并注意它在必须wait
同时继续调用wait。 同样,您只能通过检查共享状态来判断是否可以停止等待。 共享状态是您的责任-条件变量是无状态的。
我有一个消费者和两个生产者。
错误。 您有2个生产者和一个采样器。 什么都没有消耗。
您可能想要的是(简化后):
#include<deque>
#include<thread>
#include<iostream>
#include<mutex>
#include<chrono>
#include <condition_variable>
using namespace std;
deque<double> testvec;
mutex mtx;
condition_variable cv;
auto producer = [](int i)
{
while(1)
{
std::unique_lock<std::mutex> ulck(mtx);
testvec.push_back(i);
ulck.unlock();
cv.notify_all();
i++;
std::this_thread::sleep_for (std::chrono::milliseconds(i));
}
};
void consume()
{
while(1)
{
std::unique_lock<std::mutex> ulck(mtx); //locks shared data
// wait until there is something to consume...
cv.wait(ulck, [&]{return not testvec.empty(); });
/// ... consume it...
auto val = testvec.front();
testvec.pop_front();
/// ... now unlock and work with the consumed data while unlocked
ulck.unlock();
/// ... do work
cout<<"last value: " << val <<endl;
}
}
int main( int argc, char ** argv )
{
std::thread t1(producer, 222);
std::thread t2(producer, 888);
std::thread t3(consume);
t1.join();
t2.join();
t3.join();
}
示例输出:
last value: 222
last value: 888
last value: 223
last value: 224
last value: 225
last value: 889
last value: 226
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.