使用C++模拟哲学家问题

本实验的目的是为了模拟并结局不死锁的哲学家问题,采用C++语言进行编写程序,程序中使用“控制进食的人的数量”的方式来预防死锁,并通过多线程并发的方式来模拟哲学家决策以及控制程序。(运行代码需要支持C++11及以上的编译器)

#include <iostream>
#include <thread>
#include <mutex>
#include <random>
//using namespace std;

const int NUM_PHILOSOPHERS = 5;//定义哲学家的数量
int fork[NUM_PHILOSOPHERS]={0};
int count = 0,now = 0; // count表示已经进食了的哲学家的数量;now表示当前正在参与进食的哲学家的数量,用于控制预防死锁,模拟信号量
bool eating[NUM_PHILOSOPHERS] = {false}; // 表示每个哲学家的进食状态,进食过表示已经饱了,再发出进食指令将不再执行
char run='r';//控制模拟程序进行

int fwait(int n)//模拟wait
{
    if(!fork[n])
    {
        fork[n]=1;
        return 1;
    }else
    {
        return 0;
    }
}

void fsignal(int n)//模拟signal
{
    fork[n]=0;
}

bool checkeat(bool eating[])//检测所有哲学家的进食情况,如果所有哲学家均已进食过,则返回true
{
    for(int i=0; i < NUM_PHILOSOPHERS; ++i)//遍历所有哲学家的状态
    {
        if(!eating[i])//如果遍历到一个处于饥饿状态的哲学家,就放回false。
        {
            return false;
        }
    }
    return true;
}

void initeat(bool eating[])
{
    for(int i=0; i < NUM_PHILOSOPHERS; ++i)
    {
        eating[i]=false;
    }
}

void pcbctrl(int i)//控制线程
{
    std::cout<<"欢迎使用哲学家问题模拟程序,该程序使用“r”和“e”字符控制运行与结束,其他字符表示暂停。"<<std::endl;
    while (true)
    {
        std::cin>>run;//通过run来控制程序
        if(run=='e')
        {
            std::cout << "!Philosopher program exit!" << std::endl;
            break;
        }
        if(run=='r')
        {
            initeat(eating);//初始化eating
            count=0;//初始化已经吃了饭的哲学家的数量
        }
        if(checkeat(eating))
        {
            std::cout << "****!所有哲学家均已完成进食!****" << count << std::endl;//所有哲学家均已完成进食
        }
    }
}

void philosopher(int id) {
    std::this_thread::sleep_for(std::chrono::milliseconds(3000));//wait for 3 seconds
        int left_fork = id;//摆在左边的叉子
        int right_fork = (id + 1) % NUM_PHILOSOPHERS;//摆在右边的叉子

        while (true) {//当进食次数或者哲学家进食状态其中一个为真,则继续循环

            if(run=='e')
            {
                break;
            }
            else if(run=='r'){
                int choice = rand(); // 生成随机数,使用随机数来控制哲学家进食或者思考

                //模拟哲学家决策
                if (choice % 2 == 1) //模拟选择思考操作
                {
                    std::cout << "Philosopher " << id << " is thinking" << std::endl;// 模拟哲学家思考
                    std::this_thread::sleep_for(std::chrono::milliseconds(2000));//模拟思考时间

                }
                else if(!eating[id])//模拟选择吃饭操作,判断当前是否处于为进食的状态,若处于未进食的状态,则开始进食操作
                {

                    bool flag=true;//用于控制进食循环,知道进食成功

                    while(flag)
                    {
                        std::cout << "Philosopher " << id << " feel hungry!****" << std::endl;//模拟哲学家饥饿状态

                        if(now<NUM_PHILOSOPHERS&&!checkeat(eating))
                        {
                            int l=0,r=0,t1=0,t2=0;
                            now++;//当前正在参与进食的哲学家+1
                            while(l==0||r==0)
                            {
                                if(l==0){l= fwait(left_fork);}
                                if(l==1&&t1==0){
                                    ++t1;
                                    std::cout << "Philosopher " << id << " took the left fork" << std::endl;
                                }

                                if(r==0){r= fwait(right_fork);}
                                if(r==1&&t2==0){
                                    ++t2;
                                    std::cout << "Philosopher " << id << " took the right fork" << std::endl;
                                }

                                if(r==1&&l==1){

                                    std::cout << "Philosopher " << id << " is eating" << std::endl;
                                    eating[id] = true;//该哲学家已吃饱
                                    count++;//进食次数+1
                                    std::this_thread::sleep_for(std::chrono::milliseconds(2000));//模拟哲学家吃饭
                                    fsignal(left_fork);
                                    fsignal(right_fork);
                                    now--;//正在进食的哲学家-1
                                    flag = false;//结束循环
                                    break;

                                }
                                //forks[left_fork].unlock();
                                //forks[right_fork].unlock();
                            }

                            std::cout << "Philosopher " << id << " is full!**" << std::endl;
                        }
                    }
                }else
                {
                    std::cout << "Philosopher " << id << " is full!**" << std::endl;
                }

            }

        }
}

int main() {
    std::thread philosophers[NUM_PHILOSOPHERS];//定义哲学家线程
    std::thread pcbctrl1;//定义控制线程
    pcbctrl1= std::thread(pcbctrl,1);
    // 创建哲学家线程

    for (int i = 0; i < NUM_PHILOSOPHERS; ++i) {
        philosophers[i] = std::thread(philosopher, i);
    }

    // 加入哲学家线程
    for (int i = 0; i < NUM_PHILOSOPHERS; ++i) {
        philosophers[i].join();
        if(i==NUM_PHILOSOPHERS-1){//加入控制线程
            pcbctrl1.join();
        }
    }

        std::cout<<"程序结束!"<<std::endl;
    return 0;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mika的瑞士卷

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

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

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

打赏作者

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

抵扣说明:

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

余额充值