三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

C++多线程--条件变量

C++多线程--条件变量

条件变量可以让多线程中一个线程优先进行,其他线程处于休眠状态,当条件变量通知notify_one()其他线程开始运行时,其他处于wait()状态的线程才会醒来
然后上锁,开始执行当前线程
在wait()状态下的其他线程会先解除当前的锁,之后再进入休眠,不占用CPU,之后notify后会先判断当前的锁是否解开并且是否满足当前要求然后才会唤醒子线程
值得一提的是条件变量中使用的锁一般是unique_lock(),这个锁可以自动解锁,也可以手动解锁,这样就保证了防止像gaurd_lock一样不解锁,同时可以通过move交换使用权
wait()中一般是传入一个mutex锁和一个lambda表达式返回为bool类型

点击查看代码
condition_variable cv;//条件变量
mutex mtx;//互斥锁
bool is_ready = false;//条件变量的条件
void fun(int &a)
{unique_lock<mutex> lock(mtx);//加锁cout << "thread fun is running..." << endl;a = 1100;is_ready = true;cv.notify_one();//通知等待条件变量的线程
}
void fun2(int& a)
{unique_lock<mutex> lock(mtx);//加锁cv.wait(lock, [] {return is_ready; });//等待条件变量满足cout << "thread fun2 is running..." << endl;a = 300;
}
int main()
{int a = 10;thread t1(fun, ref(a));thread t2(fun2, ref(a));t1.join();//等等t1子线程执行完t2.join();//等等t2子线程执行完cout << "now a==" << a << endl;cout << "Hello World!" << endl;return 0;
}
而条件变量应用的场景有,生产者消费者模型,线程池,下面是生产者消费者模型

其中在生产者消费者模型中,生产完一个元素后一定要记得解锁,不然消费者没有办法拿到对应的解锁状态,没有办法被唤醒

点击查看代码
condition_variable cv;//条件变量
mutex mtx;//互斥锁
queue<int>producer_queue;
void producer()
{for (int i = 0; i < 5; i++){{unique_lock<mutex>lock(mtx);producer_queue.push(i);cout << "生产了一个元素:" << i << endl;}cv.notify_one();this_thread::sleep_for(chrono::milliseconds(100)); // 模拟生产耗时}
}
void consumer()
{while (1){unique_lock<mutex>lock(mtx);cv.wait(lock, [] {return !producer_queue.empty(); });int temp = producer_queue.front();producer_queue.pop();cout << "弹出了一个元素:" << temp << endl;if (temp == 4)break;}
}
int main()
{thread producer_thread(producer);thread consumer_thread(consumer);producer_thread.join();consumer_thread.join();return 0;
}
条件变量使用时可能会出现的坑 丢失唤醒:如果wait()在notify()之后,那可能会导致子线程一直wait(),无法执行,要保证消费者先wait(),之后生产者才notify(),保证消费者比生产者快 下面代码会因为主线程的速度快于子线程,所以会先notify(),导致子线程一直wait()
点击查看代码
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<atomic>
#include<queue>
using namespace std;
condition_variable cv;//条件变量
mutex mtx;//互斥锁
void fun()
{unique_lock<mutex> lock(mtx);cv.wait(lock);//等待条件变量的通知cout << "Thread is running..." << endl;
}
int main()
{thread t(fun);cv.notify_one();//通知一个等待线程t.join();return 0;
}
如果要修改的话需要让主线程加一个锁和判断条件,缓一下,让子线程先wait()
点击查看代码
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<atomic>
#include<queue>
using namespace std;
condition_variable cv;//条件变量
mutex mtx;//互斥锁
bool ready = false;//条件变量的标志
void fun()
{unique_lock<mutex> lock(mtx);cv.wait(lock, [] {return ready; });//等待条件变量的通知cout << "Thread is running..." << endl;
}
int main()
{thread t(fun);cv.notify_one();//通知一个等待线程{unique_lock<mutex> lock(mtx);ready = true;//设置条件变量的标志}t.join();return 0;
}
← 返回列表