C++ 线程之哲学家就餐问题

本文通过C++实现哲学家就餐问题,展示了如何利用线程和互斥锁防止死锁。创建了五个哲学家和五双筷子,哲学家尝试获取左右两双筷子以模拟进餐过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:C++标准线程库之哲学家就餐问题

#include <iostream>
#include <exception>
#include <mutex>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
#include <thread>
#include <chrono>

std::mutex outputMutex;

class Chopsticks
{
	int _i;
	std::mutex _mutex;

public:
	explicit Chopsticks() : _i(0) {}
	void seti(int i) { _i = i; }

	friend std::ostream& operator <<(std::ostream& out, const Chopsticks& chopsticks);

	// 使用筷子就是上锁
	bool use() throw(std::system_error)
	{
		try {
			return _mutex.try_lock();
		}
		catch (std::system_error& e) {
			throw e;
		}
	}
	// 放下筷子就是解锁
	void push_down() throw(std::system_error)
	{
		try {
			return _mutex.unlock();
		}
		catch (std::system_error& e) {
			throw e;
		}
	}
};

std::ostream& operator <<(std::ostream& out, const Chopsticks& chopsticks)
{
	out << " 筷子: " << chopsticks._i << " ";
	return out;
}

class Philosopher
{
	int _i;
	// 拿某个筷子
	bool _take(Chopsticks& chopsticks)
	{
		if (chopsticks.use()) {
			std::lock_guard<std::mutex> lock(outputMutex);
			std::cout << "哲学家: " << _i << "拿到" << chopsticks << std::endl;
			fflush(stdout);
			return true;
		}
		else {
			std::lock_guard<std::mutex> lock(outputMutex);
			std::cout << "----------------抢夺失败, 哲学家: " << _i << chopsticks << std::endl;
			fflush(stdout);
			return false;
		}
	}
	// 抢夺
	void _seizure(Chopsticks& lc, Chopsticks& rc)
	{
		for(int ki = 0; ki < 100; ki++)
		{
			{
				std::lock_guard<std::mutex> lock(outputMutex);
				std::cout << "哲学家: " << _i << " 开始抢筷子..." << std::endl;
				fflush(stdout);
			}
			// 先拿左边,在那右边
			if (_take(lc)) 
			{
				if (_take(rc)) 
				{
					std::lock_guard<std::mutex> lock(outputMutex);
					std::cout << "哲学家: " << _i << "吃饭" << std::endl;
					std::cout << "哲学家: " << _i << "放下" << rc << std::endl;
					fflush(stdout);
					rc.push_down();
				}

				std::lock_guard<std::mutex> lock(outputMutex);
				std::cout << "哲学家: " << _i << "放下" << lc << std::endl;
				fflush(stdout);
				lc.push_down();
			}
			// 休息1s
			//std::this_thread::sleep_for(std::chrono::duration<double>(0.1));
		}
	}

public:
	explicit Philosopher() : _i(0) {}
	void seti(int i) { _i = i; }
	// 可调用的	
	void operator() (Chopsticks& lc, Chopsticks& rc)
	{
		_seizure(lc, rc);
	}
};

int main()
{
	// 5个哲学家,5个筷子	
	std::vector<Philosopher> philosophers(5);
	std::vector<Chopsticks> chopsticks(5);
	std::vector<std::thread> threads;

	// 设置序号	
	for (int i = 0; i < 5; ++i) 
	{
		philosophers.at(i).seti(i + 1);
		chopsticks.at(i).seti(i + 1);
	}
	// 开启线程	
	for (int i = 0; i < 4; ++i) 
	{
		std::thread thread(philosophers.at(i), std::ref(chopsticks.at(i)), std::ref(chopsticks.at(i + 1)));
		threads.push_back(std::move(thread));
	}
	std::thread thread(philosophers.at(4), std::ref(chopsticks.at(4)), std::ref(chopsticks.at(0)));
	threads.push_back(std::move(thread));

	std::for_each(threads.begin(), threads.end(), [](std::thread& t) {t.join();});
	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值