赞
踩
生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
这是我在Linux多线程中写过的一篇文章,里面详细讲解了信号量和互斥锁解决多线程的生产者与消费者模式:
关于【C++】多线程,我在之前一篇中说过:
- const int MAX_ITEM = 20; //双端队列最大长度
- std::mutex mx; //全局锁
- std::condition_variable cv; //条件变量cv
- class Queue
- {
- public:
- void put(int val, int index) //入队函数
- {
- std::unique_lock<std::mutex> lock(mx); //类似于智能指针的智能锁,不需要手动解锁
- while (q.size() == MAX_ITEM) //队列满了之后,等待
- {
- cv.wait(lock);
- }
- q.push_back(val); //入队
- cv.notify_all(); //唤醒
- cout << "producer: " << index << "val : " << "生产者" << val << endl;
- }
- int get(int index) //出队函数
- {
- unique_lock<std::mutex> lock(mx); //类似于智能指针的智能锁,不需要手动解锁
- while (q.empty()) //队列空了等待
- {
- cv.wait(lock);
- }
- int val = q.front(); //出队函数
- q.pop_front(); //队头出,队尾加
- cv.notify_all();
- cout << "Consumer : " << index << " val : " << val << endl;
- return val;
- }
- private:
- deque<int> q;
- };
- void producer(Queue* q, int index)
- {
- for (int i = 0; i < 100; ++i)
- {
- q->put(i, index); //调用class queue中的put函数
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- }
- }
- void consumer(Queue* q, int index)
- {
- for (int i = 0; i < 100; ++i)
- {
- q->get(index); //调用class queue中的get函数
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- }
- }
- int main()
- {
- Queue* q = new Queue();
- thread p1(producer, q, 1);
- thread s1(consumer, q, 1);
- p1.join();
- s1.join();
- return 0;
- }

这个代码也比较简单,就不多说了,上面注释也很详细!!!
看一下运行结果:因为我在消费者函数和生产者函数中的睡眠时间都是100,所以我们的生产者和消费者就是生产一个,消费一个这个情况
下面来代码:
- template<class T> //模板类
- class Queue
- {
- enum { QUSIZE = 8 }; //循环队列大小为8
-
- T* data; //指针指向循环队列连续空间
- int front; //队头
- int rear; //队尾
- int size; //当前队列的元素个数
- int maxsize; //队列最大大小
- public:
- Queue() :data(nullptr), front(0), rear(0), size(0), maxsize(QUSIZE)
- {
- data = new T[maxsize];
- }
- ~Queue()
- {
- free(data);
- data = nullptr;
- front = rear = -1;
- size = 0;
- maxsize = 0;
- }
-
- int Capt() const { return maxsize; } //求队列最大元素个数的函数
- int Size() const { return size; } //求现有元素个数的函数
- bool Empty() const { return Size() == 0; } //判空函数
- bool Full() const { //判满函数
- return Size() == maxsize;
- }
- bool Push(const T& val) //入队函数
- {
- if (Full()) return false;
- data[rear] = val;
- rear = (rear + 1) % maxsize; //上面说到最大值为8,也就是说存储下标为0到7
- size += 1;
- return true;
- }
- bool Front(T& val) //出队函数
- {
- if (Empty()) return false;
- val = data[front];
- front = (front + 1) % maxsize;//上面说到最大值为8,也就是说存储下标为0到7
- size -= 1;
- return true;
- }
- };
-
- Queue<int> iq; //实例化iq
- std::mutex mx; //全局锁mx
- std::condition_variable cv; //条件变量cv
- const int maxsize = iq.Capt(); //最大元素个数
-
- int number = 0; // 100;
- void producer(int index)
- {
- std::unique_lock<std::mutex> lock(mx); //类似于智能指针的智能锁
- for (int i = 0; i < 100; i++)
- {
- cv.wait(lock, []()->bool {return !iq.Full(); }); //lambda表达式
- iq.Push(number); //上述lambda表达式为真退出,所以就不为full时为退出
- cout << "product " << number << endl;
- number++;
- cv.notify_all();
- }
- }
-
- void consumer(int index)
- {
- std::unique_lock<std::mutex> lock(mx);
- for (int i = 0; i < 100; i++)
- {
- cv.wait(lock, []()->bool {return !iq.Empty(); });//lambda表达式中为真退出等待不为NULL时,退出wait
- int val = 0;
- iq.Front(val);
- cout << "consumer " << val << endl;
- cv.notify_all();
- }
- }
-
- int main()
-
- {
- std::thread pth1(producer, 1); //生产者
- std::thread pth2(consumer, 2); //消费者
-
- pth1.join();
- pth2.join();
-
- return 0;
- }

运行结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。