c++11 生产者和消费者模型

xiaoxiao2021-02-28  94

一段简单的示例代码

#include <iostream> #include <thread> #include <mutex> #include <condition_variable> int i = 0; std::mutex mtx; std::condition_variable condition_in, condition_out; void in(int id) { while (true) { //(1) std::unique_lock<std::mutex> in(mtx); condition_in.wait(in, [id](){ std::cout << "condition_in.wait id:" << id << std::endl; return i < 5; }); std::cout << "thread id:"<<id<<"# "<<"===>"<<++i<<std::endl; //(2) condition_out.notify_one(); //(3) } } void out(int id) { while (true) { std::unique_lock<std::mutex> in(mtx); condition_out.wait(in, [id](){ std::cout << "condition_out.wait id: " << id <<std::endl; return i > 1; }); i -= 2; std::cout << "thread id:" << id<<"# "<<"===>" <<i << std::endl; condition_in.notify_one(); } } void main() { std::thread t1(in,0); std::thread t2(out,1); //std::thread t3(out,2); //std::thread t4(out,3); //std::thread t5(out,4); t1.join(); }

std::unique_lock

std::unique_lock 是一个使用RAII机制来管理 std::mutex 的一个类,相比于 std::lock_guard 有更灵活的方式,但会比 std::lock_guard 使用更多的空间。

Member functions

Locking/unlocking

lock try_lock try_lock_for try_lock_until unlock

Modifiers

operator= (Move-assign unique_lock) swap release

Observers

owns_lock operator bool (Return whether it owns a lock) mutex

运行结果

单消费者单生产者

condition_in.wait id:0 thread id:0# ===>1 condition_out.wait id: 1 condition_in.wait id:0 thread id:0# ===>2 condition_in.wait id:0 thread id:0# ===>3 condition_out.wait id: 1 thread id:1# ===>1 condition_in.wait id:0 thread id:0# ===>2 condition_out.wait id: 1 thread id:1# ===>0 condition_in.wait id:0 thread id:0# ===>1 condition_out.wait id: 1 condition_in.wait id:0 thread id:0# ===>2 condition_in.wait id:0 thread id:0# ===>3 condition_out.wait id: 1 thread id:1# ===>1 condition_in.wait id:0 thread id:0# ===>2 condition_out.wait id: 1 thread id:1# ===>0

结果大致如预期,但是通过观察发现产品的个数总是以0->1->2->3->1->2->0的规律变化,按理说每次产品增加到2之后唤醒消费者线程应该就会将2个产品取走了。通过分析输出日志,应该是因为被condition阻塞的线程从唤醒到重新上锁的时间要长于 std::unique_lock 锁争用时直接上锁的时间。另外,启动消费者和生产者线程的先后顺序也会影响刚开始的输出序列,但整体的变化规律不会变。在(1)处插入

if(i > 1)

然后先启动t2,再启动t1线程,仍然可以观察到相同序列,基本证明猜想正确。 多消费者多生产者的情况也完全符合预期。不过经过一番尝试,并没有模拟出虚假唤醒的情况,有待进一步考察。

转载请注明原文地址: https://www.6miu.com/read-85024.html

最新回复(0)