生产者消费者
#include <iostream> #include <string> #include <thread> #include <mutex> #include <condition_variable> #include <deque> #include <objbase.h> #define GUID_LEN 64 using namespace std; static int kItemsToProduce = 1; static bool g_go_on_push_flag = true; static bool g_go_on_send_flag = true; std::mutex stdoutMutex;//多线程标准输出 同步锁 struct FrameRepository { deque<std::string> frame_queue; // 这里用队列代表仓库缓冲区 int MaxSize = 10; // 仓库所容纳的产品最大个数 std::mutex mtx; // 互斥量,保护产品缓冲区 std::condition_variable repository_notFull; // 条件变量, 指产品仓库缓冲区不为满 std::condition_variable repository_notEmpty; // 条件变量, 指产品仓库缓冲区不为空 }gItemRepository; // 产品库全局变量,生产者和消费者操作该变量. typedef struct FrameRepository FrameRepository; std::string generateUUID() { char buffer[GUID_LEN] = { 0 }; GUID guid; if (CoCreateGuid(&guid)) { fprintf(stderr, "create guid error\n"); return std::string(); } _snprintf_s(buffer, sizeof(buffer), "%08X-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); return std::string(buffer); } // 生产 产品 void PushFrameItem(FrameRepository &itemRepo, std::string frame_info) { std::unique_lock<std::mutex> lock(itemRepo.mtx); //while (itemRepo.itemQueue.size() >= itemRepo.MaxSize) // 判断当前仓库满了 //{ // { // std::lock_guard<std::mutex> lock(stdoutMutex); // cout << "仓库满了,生产者等待中..." << "thread id = " << std::this_thread::get_id() << endl; // } // itemRepo.repository_notFull.wait(lock); // 等待信号量释放锁 生产者等待"仓库缓冲区不为满"这一条件发生(将会跳出循环). //} itemRepo.repository_notFull.wait(lock, [&itemRepo] { bool full = itemRepo.frame_queue.size() >= itemRepo.MaxSize; if (full) { std::lock_guard<std::mutex> lock(stdoutMutex); itemRepo.frame_queue.pop_front(); if (itemRepo.frame_queue.size() < itemRepo.MaxSize) cout << "clear" << endl; cout << "仓库满了,生产者等待中..." << "thread id = " << std::this_thread::get_id() << endl; } return !full; }); itemRepo.frame_queue.push_back(frame_info); // 仓库放入产品 itemRepo.repository_notEmpty.notify_all(); // 通知消费者仓库不为空 lock.unlock(); // 释放锁 } // 消费 产品 std::string SendFrameItem(FrameRepository &itemRepo) { std::string frame_info; std::unique_lock<std::mutex> lock(itemRepo.mtx); //while (itemRepo.itemQueue.empty()) // 判断当前仓库空了,等待 //{ // { // std::lock_guard<std::mutex> lock(stdoutMutex); // cout << "仓库空了,消费者等待中..." << "thread id = " << std::this_thread::get_id() << endl; // } // itemRepo.repository_notEmpty.wait(lock);// 消费者等待"仓库缓冲区不为空"这一条件发生.(等待信号跳出循环) //} // 等待信号不为空的通知,wait 第二参数为true时 向下执行,否则一直等待 itemRepo.repository_notEmpty.wait(lock, [&itemRepo] { bool empty = itemRepo.frame_queue.empty(); if (empty) { std::lock_guard<std::mutex> lock(stdoutMutex); cout << "仓库空了,消费者等待中..." << "thread id = " << std::this_thread::get_id() << endl; } return !empty; }); frame_info = itemRepo.frame_queue.front(); itemRepo.frame_queue.pop_front(); itemRepo.repository_notFull.notify_all(); lock.unlock(); return frame_info; } // 生产者任务 void PushFrameTask() { while (g_go_on_push_flag) { //std::this_thread::sleep_for(std::chrono::milliseconds(500)); std::string uuid = generateUUID(); if (uuid.empty()) return; PushFrameItem(gItemRepository, uuid); // 生产产品 { std::lock_guard<std::mutex> lock(stdoutMutex); cout << "生产: " << kItemsToProduce << " UUID:" << uuid << endl; } kItemsToProduce++; } } // 消费者任务 void SendFrameTask() { static int consume_cnt = 0; while (true) { std::this_thread::sleep_for(std::chrono::milliseconds(20)); if (!g_go_on_send_flag) if (consume_cnt == kItemsToProduce) break; //this_thread::sleep_for(std::chrono::seconds(1)); std::string item = SendFrameItem(gItemRepository); // 消费产品 { std::lock_guard<std::mutex> lock(stdoutMutex); cout << "消费: " << consume_cnt + 1 << " UUID:" << item << endl; } consume_cnt++; } } int main() { std::thread push(PushFrameTask); std::thread send(SendFrameTask); push.detach(); send.detach(); std::this_thread::sleep_for(std::chrono::seconds(20)); g_go_on_push_flag = false; g_go_on_send_flag = false; system("pause"); return 0; }