用pv操作实现 吃水果问题(C++语言)

/**
作者:wwj
时间:2012/4/12
功能:实现吃水果问题

**题目内容:桌子有一只盘子,只允许放一个水果,父亲专向盘子放苹果,母亲专向盘子放桔子
儿子专等吃盘子的桔子,女儿专等吃盘子的苹果。只要盘子为空,父亲或母亲就可以向盘子放水果,
仅当盘子有自己需要的水果时,儿子和女儿可从盘子取出。请给出四个人之间的同步关系,并用
pv操作实现四个人的正确活动的问题。**

**题目分析:父亲和女儿是相互制约的,父亲进程执行完即往盘中放入苹果后,女儿进程才能执行即吃苹果,是同步关系;
母亲和儿子是相互制约的,母亲进程执行完即往盘中放入桔子,儿子进程才能执行即吃桔子,也是同步关系
而父亲和母亲这两个进程不能同时进行,是互斥关系;**

 **/


#include<windows.h>
#include<iostream>
using namespace std;


//声明句柄
HANDLE EmptyPlate;
HANDLE Apple;
HANDLE orange;
HANDLE fatherThread;
HANDLE motherThread;
HANDLE sonThread;
HANDLE daughterThread;


//线程函数声明
DWORD WINAPI father(LPVOID IpParameter);
DWORD WINAPI mother(LPVOID IpParameter);
DWORD WINAPI daughter(LPVOID IpParameter);
DWORD WINAPI son(LPVOID IpParameter);


int main()
{
	//创建信号量
	EmptyPlate = CreateSemaphore(NULL,1,1,NULL);  //盘子
	Apple = CreateSemaphore(NULL,0,1,NULL);	//苹果
	orange = CreateSemaphore(NULL,0,1,NULL); //桔子

	//创建线程
	fatherThread = CreateThread(NULL,0,father,NULL,0,NULL);
	motherThread = CreateThread(NULL,0,mother,NULL,0,NULL);
	daughterThread = CreateThread(NULL,0,daughter,NULL,0,NULL);
	sonThread = CreateThread(NULL,0,son,NULL,0,NULL);
	


	//等线程的结束
	WaitForSingleObject(fatherThread,INFINITE); 
	WaitForSingleObject(motherThread,INFINITE); 
	WaitForSingleObject(daughterThread,INFINITE); 
	WaitForSingleObject(sonThread,INFINITE); 

	//关闭线程句柄
	CloseHandle(fatherThread);	
	CloseHandle(motherThread);
	CloseHandle(daughterThread);
	CloseHandle(sonThread);

	//关闭信号量句柄
	CloseHandle(EmptyPlate);	
	CloseHandle(Apple);
	CloseHandle(orange);
	return 0;	

}


	//父亲线程函数
	DWORD WINAPI father(LPVOID IpParameter)
	{
		for(int i = 0; i < 5; ++i){
		WaitForSingleObject(EmptyPlate, INFINITE);	// P操作
		// 开始临界区
		cout << "\nFather往盘中放一个水果\n";
		// 结束临界区
		ReleaseSemaphore(Apple, 1, NULL);	// V操作
		}
		return 0;
	}

	//母亲线程函数
	DWORD WINAPI mother(LPVOID IpParmeter)
	{
	
	for(int i = 0; i < 5; ++i){
		WaitForSingleObject(EmptyPlate, INFINITE);	// P操作
		// 开始临界区
		cout << "\nMother往盘中放一个桔子\n";
		// 结束临界区
		ReleaseSemaphore(orange, 1, NULL);	// V操作
	}
	return 0;
	}



	//女儿线程函数
	DWORD WINAPI daughter(LPVOID IpParameter)
	{
		while(1)
		{
			WaitForSingleObject(Apple,INFINITE); //p操作
			cout<<"女儿吃苹果"<<endl;
			ReleaseSemaphore(EmptyPlate,1,NULL); //v操作
		
		}

		return 0;
	}


	//儿子线程函数
	DWORD WINAPI son(LPVOID IpParameter)
	{
		while(1)
		{
			WaitForSingleObject(orange,INFINITE); //p操作
			cout<<"儿子吃苹果"<<endl;
			ReleaseSemaphore(EmptyPlate,1,NULL); //v操作

		}
		return 0;
	}


C++中,我们可以使用`std::mutex`、`std::condition_variable`以及`std::queue`来模拟这个场景,以便实现四个进程之间的同步控制。这里是一个简化的示例: ```cpp #include <iostream> #include <queue> #include <thread> #include <mutex> #include <condition_variable> class FruitQueue { private: std::queue<int> fruits; std::mutex mutex_; std::condition_variable cond_; public: void put(int fruit, bool parent) { std::unique_lock<std::mutex> lock(mutex_); if (fruits.size() == 5) { lock.unlock(); cond_.wait(lock, [this, parent] { return !parent || fruits.size() != 5; }); } fruits.push(fruit); if (!parent) cond_.notify_one(); // 父亲放下水果后通知孩子 lock.unlock(); } int take(bool& is_apple, bool& is_orange) { std::unique_lock<std::mutex> lock(mutex_); while (fruits.empty()) { if (is_apple && is_orange) // 如果双方都等待,则阻塞 cond_.wait(lock, [] { return fruits.size() > 0 || !(*is_apple || *is_orange); }); else if (*is_apple) // 儿子等待苹果 cond_.wait(lock, [this, &is_apple] { return fruits.front() == 1 || fruits.empty(); }); else if (*is_orange) // 女儿等待橘子 cond_.wait(lock, [this, &is_orange] { return fruits.front() == 2 || fruits.empty(); }); } int taken = fruits.front(); fruits.pop(); lock.unlock(); return taken; } }; int main() { FruitQueue queue; std::thread father([](FruitQueue& q) { for (size_t i = 1; i <= 10; ++i) q.put(i, true); // 爸爸放苹果 }, std::ref(queue)); std::thread mother([](FruitQueue& q) { for (size_t i = 11; i <= 20; ++i) q.put(i, false); // 妈妈放橘子 }, std::ref(queue)); bool son_apple, daughter_orange; int taken_by_son = queue.take(son_apple, daughter_orange); std::cout << "Son took an apple: " << taken_by_son << '\n'; bool another_taken; int taken_by_daughter = queue.take(another_taken, daughter_orange); std::cout << "Daughter took a fruit: " << taken_by_daughter << " (another taken: " << another_taken << ')\n'; father.join(); mother.join(); return 0; } ``` 在这个例子中,我们创建了一个`FruitQueue`类,用于存储水果和进行同步。爸爸和妈妈分别作为单独的线程往队列中添加苹果和橘子,儿子和女儿则是消费者,通过`take`函数等待并取走水果。`put`函数会检查队列是否满,并在满的情况下等待一个空位。`take`函数会等待直到有对应的水果可用。 注意这只是一个简化版本,实际应用中可能会需要更复杂的条件判断和错误处理。此外,对于生产者消费者模型,还可以考虑使用`std::atomic`和无锁数据结构来提高性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小巫技术博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值