日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

【C++】多线程(链式、循环队列)实现生产者消费者模式

發布時間:2023/11/27 生活经验 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C++】多线程(链式、循环队列)实现生产者消费者模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

生產者消費者模式:

????????生產者消費者問題(英語:Producer-consumer problem),也稱有限緩沖問題(英語:Bounded-buffer problem),是一個多線程同步問題的經典案例。該問題描述了兩個共享固定大小緩沖區的線程——即所謂的“生產者”和“消費者”——在實際運行時會發生的問題。生產者的主要作用是生成一定量的數據放到緩沖區中,然后重復此過程。與此同時,消費者也在緩沖區消耗這些數據。該問題的關鍵就是要保證生產者不會在緩沖區滿時加入數據,消費者也不會在緩沖區中空時消耗數據。
?

這是我在Linux多線程中寫過的一篇文章,里面詳細講解了信號量和互斥鎖解決多線程的生產者與消費者模式:

Linux信號量與互斥鎖解決生產者與消費者問題_神廚小福貴!的博客-CSDN博客先來看什么是生產者消費者問題:生產者消費者問題(英語:Producer-consumer problem),也稱有限緩沖問題(英語:Bounded-buffer problem),是一個多線程同步問題的經典案例。該問題描述了兩個共享固定大小緩沖區的線程——即所謂的“生產者”和“消費者”——在實際運行時會發生的問題。生產者的主要作用是生成一定量的數據放到緩沖區中,然后重復此過程。與此同時,消費者也在緩沖區消耗這些數據。該問題的關鍵就是要保證生產者不會在緩沖區滿時加入數據,消費者也不會在緩沖區中空時消耗數據https://blog.csdn.net/qq_45829112/article/details/121580819下圖就是生產者消費者的大致模型:

上圖所示,我們能不能在【C++】中使用多線程使得,一邊生產,一邊消費呢???

關于【C++】多線程,我在之前一篇中說過:

【C++】多線程thread_神廚小福貴!的博客-CSDN博客進程和線程的區別:進程是資源分配的最小單位,線程是CPU調度的最小單位 進程有自己的獨立地址空間,線程共享進程中的地址空間 進程的創建消耗資源大,線程的創建相對較小進程的切換開銷大,線程的切換開銷相對較小 進程:程序執行的過程叫進程。線程:進程內部的一條執行序列或執行路徑,一個進程可以包含多條線程(多線程)!每個進程最少有一個線程,例如下面代碼:#include <iostream>using namespace std; int main(){ https://blog.csdn.net/qq_45829112/article/details/123521502?spm=1001.2014.3001.5502

下面我們拿鏈隊列循環隊列分別實現我們的生產者消費者模式

鏈隊列實現生產者消費者:queue來實現:

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 };  //循環隊列大小為8T* 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到7size += 1;return true;}bool Front(T& val)  //出隊函數{if (Empty()) return false;val = data[front];front = (front + 1) % maxsize;//上面說到最大值為8,也就是說存儲下標為0到7size -= 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時,退出waitint 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;
}

運行結果:?

?

總結

以上是生活随笔為你收集整理的【C++】多线程(链式、循环队列)实现生产者消费者模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。