![[c++多线程并发 基础入门] 1.3条件变量condition,第1张 [c++多线程并发 基础入门] 1.3条件变量condition,第1张](/aiimages/%5Bc%2B%2B%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%B9%B6%E5%8F%91+%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8%5D+1.3%E6%9D%A1%E4%BB%B6%E5%8F%98%E9%87%8Fcondition.png)
#include
#include
#include
#include
#include
std::mutex mtx;
std::deque<int> q;
//producer
void task1()
{
int i = 0;
while(true)
{
std::unique_lock<std::mutex> lock(mtx);
q.push_back(i);
//this thread delay 10ms
std::this_thread::sleep_for(std::chrono::milliseconds(10));
if(i < 99)
{
i++;
}
else
{
i = 0;
}
}
}
//consumer
void task2()
{
int data = 0;
while(true)
{
std::unique_lock<std::mutex> lock(mtx);
if(!q.empty())
{
data = q.front();
q.pop_front();
std::cout<< "get value from que: "<<data<<std::endl;
}
//this thread delay 10ms
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int main(int argc, const char * argv[])
{
std::thread t1(task1);
std::thread t2(task2);
t1.join();
t2.join();
return 0;
}
使用延时std::this_thread::sleep_for(std::chrono::milliseconds(10)); 表示当前线程休眠一段时间,休眠期间不与其他线程竞争CPU,根据线程需求,等待若干时间。
延时过长,消费者线程不能及时的从队列里面取数据
延时过短,对CPU的占用率不能很大缓解
例子:
#include
#include
#include
#include
#include
#include
std::mutex mtx;
std::deque<int> q;
std::condition_variable cv;
//producer
void task1()
{
int i = 0;
while(true)
{
std::unique_lock<std::mutex> lock(mtx);
q.push_back(i);
cv.notify_one();
if(i < 20)
{
i++;
}
else
{
i = 0;
}
}
}
//consumer
void task2()
{
int data = 0;
while(true)
{
std::unique_lock<std::mutex> lock(mtx);
if(q.empty())
{
cv.wait(lock);
//cv.wait(lock) 相当于下面两行
//lock.unlock();
//cv.wait();
}
if(!q.empty())
{
data = q.front();
q.pop_front();
std::cout<< "get value from que: "<<data<<std::endl;
}
}
}
int main(int argc, const char * argv[]) {
std::thread t1(task1);
std::thread t2(task2);
t1.join();
t2.join();
return 0;
}
macOS xcode 运行结果:
get value from que: 0
get value from que: 1
get value from que: 2
get value from que: 3
get value from que: 4
get value from que: 5
get value from que: 6
get value from que: 7
get value from que: 8
get value from que: 9
get value from que: 10
get value from que: 11
get value from que: 12
get value from que: 13
get value from que: 14
get value from que: 15
get value from que: 16
get value from que: 17
get value from que: 18
get value from que: 19
get value from que: 20
get value from que: 0
get value from que: 1
get value from que: 2
get value from que: 3
get value from que: 4
get value from que: 5
get value from que: 6
get value from que: 7
get value from que: 8
get value from que: 9
get value from que: 10
get value from que: 11
get value from que: 12
get value from que: 13
get value from que: 14
get value from que: 15
get value from que: 16
get value from que: 17
get value from que: 18
get value from que: 19
get value from que: 20
get value from que: 0
get value from que: 1
get value from que: 2
get value from que: 3
get value from que: 4
get value from que: 5
get value from que: 6
get value from que: 7
get value from que: 8
get value from que: 9
get value from que: 10
get value from que: 11
get value from que: 12
get value from que: 13
get value from que: 14
get value from que: 15
get value from que: 16
get value from que: 17
get value from que: 18
get value from que: 19
get value from que: 20
get value from que: 0
get value from que: 1
get value from que: 2
…
…
#include
#include
#include
#include
#include
#include
std::mutex mtx;
std::deque<int> q;
std::condition_variable cv;
//producer
void task1()
{
int i = 0;
while(true)
{
std::unique_lock<std::mutex> lock(mtx);
q.push_back(i);
cv.notify_one();
if(i < 2000000000)
{
i++;
}
else
{
i = 0;
}
}
}
//consumer1
void task2()
{
int data = 0;
while(true)
{
std::unique_lock<std::mutex> lock(mtx);
if(q.empty())
{
cv.wait(lock);//意思是下面两句,解锁再等待
//lock.unlock();
//cv.wait();
}
data = q.front();
q.pop_front();
std::cout<< "get value from que: "<<data<<std::endl;
}
}
//consumer2
void task3()
{
int data = 0;
while(true)
{
std::unique_lock<std::mutex> lock(mtx);
if(q.empty())
{
cv.wait(lock);//意思是下面两句,解锁再等待
//lock.unlock();
//cv.wait();
}
data = q.front();
q.pop_front();
std::cout<< "get value from que: "<<data<<std::endl;
}
}
int main(int argc, const char * argv[]) {
std::thread t1(task1);
std::thread t2(task2);
std::thread t3(task2);
t1.join();
t2.join();
t3.join();
return 0;
}
以上可能造成虚假唤醒,当生产者q.push_back(i);时:消费者1判断队列不为空 后取出队列头的元素并移除,生产者notify_one后通知消费者2,消费者2从wait中唤醒,然后又去取队列头部数据,此时队列头部数据已经被消费者1移除了,报错,这就是虚假唤醒
解决方法:
把消费者1, 消费者2中的 if改成while
if(q.empty())
{
cv.wait(lock);//意思是下面两句,解锁再等待
//lock.unlock();
//cv.wait();
}
改成:
while(q.empty())
{
cv.wait(lock);//意思是下面两句,解锁再等待
//lock.unlock();
//cv.wait();
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)