生产者 消费者模型(C++)
class AA
{
// 互斥锁
mutex m_mutex;
// 条件变量
condition_variable m_cond;
// 缓存队列,底层deque
queue<string, deque<string>> m_q;
public:
// 生产数据 num指定数据的个数
void incache(int num)
{
lock_guard<mutex> lock(m_mutex);
for (int ii = 0; ii < num; ii++)
{
static int index = 1;
string message = to_string(index++) + "- woman";
m_q.push(message);
}
m_cond.notify_one();
// 完成后lock_guard 会自动释放锁
}
// 消费者线程任务函数
void outcache()
{
string message;
while (true)
{
{
// 把互斥锁换成unique_lock<mutex> == 申请加锁
// 转成unique_lock 是为了使用其lock 和 unlock方法
unique_lock<mutex> lock(m_mutex);
// 如果队列中没有数据则等待 否则直接处理
// 可能存在虚假唤醒, 对于拿不到数据的线程就是虚假唤醒
// 若唤醒后队列中无待处理数据,应当等待下一次唤醒,所以此处用while而不用if
while (m_q.empty())
{
// 1) 解开互斥锁 2)阻塞,等待被唤醒 3)给互斥锁加锁
// 所以 当前面的线程运行wait()时就可以先解开互斥锁,方便后面的线程进行lock
// 所有的线程都在wait()队列中,而不是在lock()队列中
m_cond.wait(lock);
}
// 数据元素出队
message = m_q.front();
m_q.pop();
// 也可以取消作用域 手动解锁
}
// 数据取出后即可不需要锁,因此取出数据后直接释放锁,固添加作用域
cout << "Thread: " << this_thread::get_id() << ", " << message << endl;
// 假设需要一毫秒来处理数据
this_thread::sleep_for(chrono::milliseconds(1));
}
}
};
void test6()
{
AA aa;
// 创建三个消费者线程
thread t1(&AA::outcache, &aa);
thread t2(&AA::outcache, &aa);
thread t3(&AA::outcache, &aa);
this_thread::sleep_for(chrono::seconds(2));
aa.incache(3);
this_thread::sleep_for(chrono::seconds(3));
aa.incache(5);
t1.join();
t2.join();
t3.join();
}
int main(int, char **)
{
test6();
}