生产者每次生产1个随机整数,放到缓冲区中;消费者每次从缓冲区中按生产顺序取出1个整数。每次缓冲区发生变化,打印放入/取出的数,以及缓冲当前大小。
情形1:初始为空,生产速率2/秒,消费速率1/秒
情形2:初始全满,生产速率1/秒,消费速率2/秒
情形3:初始半满,生产速率=消费速率
参考这个博客进行了一些改动
三个输入参数分别是当前的buffer中item的数量,生产者生产速率,消费者消费速率。
#include <mutex>
#include <condition_variable>
#include <windows.h>
#include <thread>
#include<iostream>
using namespace std;
static const int buffer_size = 128; // 缓存大小
static const int item_total = 300; //总共要生产 item_total个item
int produce_num = 1;
int consume_num = 1;
// 缓存结构体, 使用循环队列当做缓存
struct Buffer
{
int buffer[buffer_size];
size_t read_position; // 当前读位置
size_t write_position; // 当前写位置
mutex mtx; // 读写互斥
//条件变量
condition_variable not_full;
condition_variable not_empty;
} buffer_res;
typedef struct Buffer Buffer;
int get_write_position(Buffer *b)
{
for (int i = 0; i < buffer_size; i++)
{
if (0 == b->buffer[i])
{
return i;
}
}
return buffer_size;
}
int get_read_position(Buffer *b)
{
for (int i = 0; i < buffer_size; i++)
{
if (0 != b->buffer[i])
{
return i;
}
}
return buffer_size;
}
void porduce_item(Buffer *b)
{
unique_lock<mutex> lock(b->mtx); //设置互斥锁
while (1)
{
b->write_position = get_write_position(b);
if (b->write_position == buffer_size)
{
//当前缓存已经满了
cout << "buffer is full now, producer is wating....." << endl;
(b->not_full).wait(lock); // 等待缓存非full
}
else
{
break;
}
}
int item = rand() % buffer_size + 1;
cout << "produce item: " << item << " in " << b->write_position << " ***" << endl;
// 向缓存中添加item
(b->buffer)[b->write_position] = item;
(b->not_empty).notify_all();
lock.unlock();
}
int consume_item(Buffer *b)
{
unique_lock<mutex> lock(b->mtx);
while (1)
{
b->read_position = get_read_position(b);
if (b->read_position == buffer_size)
{
// 当前buffer 为空
cout << "buffer is empty , consumer is waiting....." << endl;
(b->not_empty).wait(lock);
}
else
{
break;
}
}
int item = (b->buffer)[b->read_position];
(b->buffer)[b->read_position] = 0;
cout << "consume item: " << item << " in " << b->read_position << endl;
(b->not_full).notify_all();
lock.unlock();
return item;
}
//生产者任务
void producer(int buf)
{
for (int i = 1; i <= item_total - buf; i++)
{
//生产item需要的时间
Sleep(20 / produce_num);
porduce_item(&buffer_res);
}
}
//消费者任务
void consumer()
{
static int cnt = 0;
while (1)
{
//消费需要的时间
Sleep(20 / consume_num);
int item = consume_item(&buffer_res);
if (++cnt == item_total)
break;
}
}
//初始化 buffer, buf空满状态,p_num为produce_num, c_num为consume_num
void init_buffer(Buffer *b, const int buf)
{
for (int i = 0; i < buf; i++)
{
b->buffer[i] = rand() % buffer_size + 1;
}
for (int i = buf; i < buffer_size; i++)
{
b->buffer[i] = 0;
}
}
int main(int argc, char **argv)
{
int buf = 0;
if (argc >= 4)
{
buf = atoi(argv[1]);
produce_num = atoi(argv[2]);
consume_num = atoi(argv[3]);
}
else
{
cout << "Please enter the initial buffer items, "
"produce_num ∈ {1,2} and consume_num ∈ {1,2}."
<< endl;
cin >> buf >> produce_num >> consume_num;
}
init_buffer(&buffer_res, buf);
thread produce(producer, buf);
thread consume(consumer);
produce.join();
consume.join();
return 0;
}