上机实现操作系统课程中的 PV 操作

各位上过《操作系统》的同学都知道进程同步这个知识点,汤小丹那本“考研指定教材”上面描述 PV 操作是用 Pascal 语言的,看着真心难受,各种题目也是要求我们纸上写程序,本人真心反感,写了都不知道对不对。下面这个程序是在 Windows 下用 C 语言写的,选的例子是经典的“生产者消费者问题”,希望对大家有所帮助。

“生产者消费者问题”的程序如下,假设有多个缓冲区,多个生产者,多个消费者。它们的数量可以在宏定义中设置。

/********************************************************************
created:	2013/11/06
created:	16:54
file base:	producer_consumer
file ext:	c
author:		Justme0 (http://blog.csdn.net/Justme0)

purpose:	生产者消费者问题
*********************************************************************/

#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <time.h>

#define WAIT_TIME		100		// 每次输出后暂停,便于观察
#define BUFFER_SIZE		2		// 缓冲区数目
#define PRODUCER_NUM	1		// 生产者数目
#define CONSUMER_NUM	1		// 消费者数目

typedef int Item;				// 产品类型

Item productID = 1;				// 产品ID
Item NOTHING_TAG = 0;			// 表明该处为空缓冲区(用于输出显示)
Item buffer[BUFFER_SIZE];		// 缓冲区(所有元素应初始化为 NOTHING_TAG)
int in = 0;						// 生产者指针(右开)
int out = 0;					// 消费者指针(左闭)

HANDLE empty;					// 消费者--生产者同步信号量
HANDLE full;					// 生产者--消费者同步信号量
HANDLE mutex;	// 互斥信号量(若给生产者、消费者分别设置互斥量,则并发度更高)

void put_item(Item item);
Item get_item();
Item produce_item();
void consume_item(Item item);
DWORD WINAPI producer(LPVOID param);
DWORD WINAPI consumer(LPVOID param);
void print_buffer();
void print_init();

/*
** 生产者进程
*/
DWORD WINAPI producer(LPVOID param) {
	Item item;
	while(TRUE)	{
		item = produce_item();

		WaitForSingleObject(empty, INFINITE);
		WaitForSingleObject(mutex, INFINITE);
		put_item(item);
		ReleaseMutex(mutex);
		ReleaseSemaphore(full, 1, NULL);
	}

	return 0;
}

/*
** 消费者进程
*/
DWORD WINAPI consumer(LPVOID param) {
	Item item;
	while(TRUE)	{
		WaitForSingleObject(full, INFINITE);
		WaitForSingleObject(mutex, INFINITE);
		item = get_item();
		ReleaseMutex(mutex);
		ReleaseSemaphore(empty, 1, NULL);

		consume_item(item);
	}

	return 0;
}

int main(int argc, char **argv) {
	int i;
	freopen("cout.txt", "w", stdout);

	// 创建各信号量
	empty = CreateSemaphore(NULL, BUFFER_SIZE, BUFFER_SIZE, NULL);
	full = CreateSemaphore(NULL, 0, BUFFER_SIZE, NULL);
	mutex = CreateMutex(NULL, FALSE, NULL);

	// 输出初始状态
	print_init();

	// 创建生产者线程
	for (i = 0; i != PRODUCER_NUM; ++i) {
		_beginthreadex(NULL, 0, producer, NULL, 0, NULL);
	}
	// 创建消费者进程
	for (i = 0; i != CONSUMER_NUM; ++i) {
		_beginthreadex(NULL, 0, consumer, NULL, 0, NULL);
	}

	while(TRUE);

	return 0;
}

void put_item(Item item) {
	Sleep(WAIT_TIME);
	printf("\n生产者投入%d\n", item);
	buffer[in] = item;
	in = (1 + in) % BUFFER_SIZE;
	print_buffer();
}

Item get_item() {
	Item item = buffer[out];
	Sleep(WAIT_TIME);
	buffer[out] = NOTHING_TAG;
	out = (1 + out) % BUFFER_SIZE;
	printf("\n消费者获取%d\n", item);
	print_buffer();
	return item;
}

Item produce_item() {
	Item item = productID++;
	printf("生产者生产出%d\n", item);
	return item;
}

void consume_item(Item item) {
	printf("消费者消费掉%d\n", item);
}

void print_buffer() {
	int i;
	for (i = 0; i != BUFFER_SIZE; ++i) {
		printf("buffer[%d]:", i);
		if (buffer[i] != NOTHING_TAG) {
			printf(" %d", buffer[i]);
		}
		if (i == out) {
			printf(" <-- 消费者");
		}
		if (i == in) {
			printf(" <-- 生产者");
		}
		printf("\n");
	}
	printf("\n");
}

void print_init() {
	printf("初始状态:\n");
	printf("生产者个数:%d\n", PRODUCER_NUM);
	printf("消费者个数:%d\n", CONSUMER_NUM);
	printf("缓冲区个数:%d\n", BUFFER_SIZE);
	printf("初始缓冲区状态:\n");
	print_buffer();
}

某次运行的结果如下

初始状态:
生产者个数:1
消费者个数:1
缓冲区个数:2
初始缓冲区状态:
buffer[0]: <-- 消费者 <-- 生产者
buffer[1]:

生产者生产出1

生产者投入1
buffer[0]: 1 <-- 消费者
buffer[1]: <-- 生产者

生产者生产出2

消费者获取1
buffer[0]:
buffer[1]: <-- 消费者 <-- 生产者

消费者消费掉1

生产者投入2
buffer[0]: <-- 生产者
buffer[1]: 2 <-- 消费者

生产者生产出3

消费者获取2
buffer[0]: <-- 消费者 <-- 生产者
buffer[1]:

消费者消费掉2

生产者投入3
buffer[0]: 3 <-- 消费者
buffer[1]: <-- 生产者

生产者生产出4

消费者获取3
buffer[0]:
buffer[1]: <-- 消费者 <-- 生产者

消费者消费掉3

生产者投入4
buffer[0]: <-- 生产者
buffer[1]: 4 <-- 消费者

生产者生产出5

消费者获取4
buffer[0]: <-- 消费者 <-- 生产者
buffer[1]:

消费者消费掉4

生产者投入5
buffer[0]: 5 <-- 消费者
buffer[1]: <-- 生产者


可以看到,程序中的 WaitForSingleObject 即 P(),ReleaseMutex 和 ReleaseSemaphore 即 V(),CreateSemaphore 用于创建资源信号量,CreateMutex 用于创建互斥信号量,mutex 是 semaphore 的特殊形式。

这是我第一次接触多线程程序,上次去面试被问到多线程完全空白,桑心啊。


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值