186 lines
6.0 KiB
C++
186 lines
6.0 KiB
C++
#include <iostream>
|
||
#include <thread>
|
||
#include <vector>
|
||
#include <chrono>
|
||
#include <random>
|
||
#include <semaphore>
|
||
#include <mutex>
|
||
#include <iomanip>
|
||
|
||
using namespace std;
|
||
|
||
// 缓冲区大小
|
||
const int BUFFER_SIZE = 5;
|
||
// 生产者数量
|
||
const int PRODUCER_COUNT = 3;
|
||
// 消费者数量
|
||
const int CONSUMER_COUNT = 2;
|
||
// 每个生产者生产的产品数量
|
||
const int PRODUCTS_PER_PRODUCER = 10;
|
||
|
||
// 缓冲区结构
|
||
struct Buffer {
|
||
vector<int> data; // 存储产品的数组
|
||
int in; // 生产者插入位置
|
||
int out; // 消费者取出位置
|
||
|
||
Buffer() : data(BUFFER_SIZE, 0), in(0), out(0) {}
|
||
};
|
||
|
||
// 全局变量
|
||
Buffer buffer; // 共享缓冲区
|
||
counting_semaphore<BUFFER_SIZE> empty_sem(BUFFER_SIZE); // 空缓冲区数量信号量
|
||
counting_semaphore<BUFFER_SIZE> full_sem(0); // 满缓冲区数量信号量
|
||
mutex buffer_mutex; // 缓冲区互斥锁
|
||
mutex output_mutex; // 输出互斥锁
|
||
int total_produced = 0; // 总生产数量
|
||
int total_consumed = 0; // 总消费数量
|
||
|
||
// 打印缓冲区状态的函数
|
||
void print_buffer_status(const string& operation, int thread_id, int product_id) {
|
||
lock_guard<mutex> lock(output_mutex);
|
||
cout << operation << " 线程" << thread_id << " 产品" << product_id << endl;
|
||
cout << "缓冲区状态: [";
|
||
for (int i = 0; i < BUFFER_SIZE; i++) {
|
||
if (i > 0) cout << ", ";
|
||
if ((buffer.out <= buffer.in && i >= buffer.out && i < buffer.in) ||
|
||
(buffer.out > buffer.in && (i >= buffer.out || i < buffer.in))) {
|
||
cout << buffer.data[i];
|
||
} else {
|
||
cout << "空";
|
||
}
|
||
}
|
||
cout << "]" << endl;
|
||
cout << "in=" << buffer.in << ", out=" << buffer.out;
|
||
cout << ", 已生产=" << total_produced << ", 已消费=" << total_consumed << endl;
|
||
cout << "----------------------------------------" << endl;
|
||
}
|
||
|
||
// 生产者函数
|
||
void producer(int producer_id) {
|
||
random_device rd;
|
||
mt19937 gen(rd());
|
||
uniform_int_distribution<> dis(100, 999); // 生成三位数产品编号
|
||
|
||
for (int i = 0; i < PRODUCTS_PER_PRODUCER; i++) {
|
||
// 生产产品(模拟生产时间)
|
||
this_thread::sleep_for(chrono::milliseconds(dis(gen) % 500 + 100));
|
||
|
||
int product = producer_id * 1000 + i + 1; // 产品编号:生产者ID*1000 + 序号
|
||
|
||
// P操作:等待空缓冲区
|
||
empty_sem.acquire();
|
||
|
||
// P操作:获取缓冲区互斥锁
|
||
{
|
||
lock_guard<mutex> lock(buffer_mutex);
|
||
|
||
// 将产品放入缓冲区
|
||
buffer.data[buffer.in] = product;
|
||
buffer.in = (buffer.in + 1) % BUFFER_SIZE;
|
||
total_produced++;
|
||
|
||
// 打印生产信息
|
||
print_buffer_status("生产者", producer_id, product);
|
||
}
|
||
|
||
// V操作:释放满缓冲区信号量
|
||
full_sem.release();
|
||
}
|
||
|
||
{
|
||
lock_guard<mutex> lock(output_mutex);
|
||
cout << "生产者" << producer_id << " 完成所有生产任务" << endl;
|
||
}
|
||
}
|
||
|
||
// 消费者函数
|
||
void consumer(int consumer_id) {
|
||
random_device rd;
|
||
mt19937 gen(rd());
|
||
uniform_int_distribution<> dis(100, 999);
|
||
|
||
// 计算每个消费者需要消费的产品数量
|
||
int products_to_consume = (PRODUCER_COUNT * PRODUCTS_PER_PRODUCER) / CONSUMER_COUNT;
|
||
if (consumer_id < (PRODUCER_COUNT * PRODUCTS_PER_PRODUCER) % CONSUMER_COUNT) {
|
||
products_to_consume++; // 处理不能整除的情况
|
||
}
|
||
|
||
for (int i = 0; i < products_to_consume; i++) {
|
||
// P操作:等待满缓冲区
|
||
full_sem.acquire();
|
||
|
||
int product;
|
||
// P操作:获取缓冲区互斥锁
|
||
{
|
||
lock_guard<mutex> lock(buffer_mutex);
|
||
|
||
// 从缓冲区取出产品
|
||
product = buffer.data[buffer.out];
|
||
buffer.data[buffer.out] = 0; // 清空该位置
|
||
buffer.out = (buffer.out + 1) % BUFFER_SIZE;
|
||
total_consumed++;
|
||
|
||
// 打印消费信息
|
||
print_buffer_status("消费者", consumer_id, product);
|
||
}
|
||
|
||
// V操作:释放空缓冲区信号量
|
||
empty_sem.release();
|
||
|
||
// 消费产品(模拟消费时间)
|
||
this_thread::sleep_for(chrono::milliseconds(dis(gen) % 300 + 150));
|
||
}
|
||
|
||
{
|
||
lock_guard<mutex> lock(output_mutex);
|
||
cout << "消费者" << consumer_id << " 完成所有消费任务" << endl;
|
||
}
|
||
}
|
||
|
||
int main() {
|
||
cout << "========== 多生产者多消费者多缓冲区同步实验 ==========" << endl;
|
||
cout << "缓冲区大小: " << BUFFER_SIZE << endl;
|
||
cout << "生产者数量: " << PRODUCER_COUNT << endl;
|
||
cout << "消费者数量: " << CONSUMER_COUNT << endl;
|
||
cout << "每个生产者生产产品数: " << PRODUCTS_PER_PRODUCER << endl;
|
||
cout << "总产品数量: " << PRODUCER_COUNT * PRODUCTS_PER_PRODUCER << endl;
|
||
cout << "========================================" << endl;
|
||
|
||
// 创建生产者线程
|
||
vector<thread> producers;
|
||
for (int i = 0; i < PRODUCER_COUNT; i++) {
|
||
producers.emplace_back(producer, i + 1);
|
||
}
|
||
|
||
// 创建消费者线程
|
||
vector<thread> consumers;
|
||
for (int i = 0; i < CONSUMER_COUNT; i++) {
|
||
consumers.emplace_back(consumer, i + 1);
|
||
}
|
||
|
||
// 等待所有生产者线程结束
|
||
for (auto& p : producers) {
|
||
p.join();
|
||
}
|
||
|
||
// 等待所有消费者线程结束
|
||
for (auto& c : consumers) {
|
||
c.join();
|
||
}
|
||
|
||
cout << "========== 实验结束 ==========" << endl;
|
||
cout << "最终统计:" << endl;
|
||
cout << "总生产数量: " << total_produced << endl;
|
||
cout << "总消费数量: " << total_consumed << endl;
|
||
|
||
if (total_produced == total_consumed &&
|
||
total_produced == PRODUCER_COUNT * PRODUCTS_PER_PRODUCER) {
|
||
cout << "实验成功!所有产品都被正确生产和消费。" << endl;
|
||
} else {
|
||
cout << "实验异常!生产和消费数量不匹配。" << endl;
|
||
}
|
||
|
||
return 0;
|
||
}
|