C++哲学家吃饭问题

问题描述

摘自百度

有五个哲学家,他们的生活方式是交替地进行思考和进餐,哲学家们共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,平时哲学家进行思考,饥饿时便试图取其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐,该哲学家进餐完毕后,放下左右两只筷子又继续思考。
约束条件
(1)只有拿到两只筷子时,哲学家才能吃饭。
(2)如果筷子已被别人拿走,则必须等别人吃完之后才能拿到筷子。
(3)任一哲学家在自己未拿到两只筷子吃完饭前,不会放下手中已经拿到的筷子。


代码实现

死锁的情况

const int philosopher_num = 5;
std::mutex chopsticks[philosopher_num];

void Philosopher(int pid){
    while (true) {
        std::unique_lock<std::mutex>lk_l(chopsticks[pid-1]);//取左边的筷子
        std::this_thread::sleep_for(100ms);//更快出现死锁(如果有的话)
        std::unique_lock<std::mutex>lk_r(chopsticks[pid % philosopher_num]);//取右边的筷子
        cout << "哲学家"<<pid<<" 线程id" << std::this_thread::get_id() <<"吃饭了" << endl;
    }
}

int main()
{
    vector<thread> threads;
    for (int i = 0; i < philosopher_num; ++i) {
        threads.push_back(thread(Philosopher,i+1));
    }

    for (int i = 0; i < philosopher_num; ++i) {
        threads[i].join();
    }
}

解决的情况1

拿两双筷子才吃饭

void Philosopher(int pid) {
	while (true) {
		std::unique_lock<std::mutex>lk_l(chopsticks[pid - 1],std::defer_lock);//取左边的筷子
        std::this_thread::sleep_for(100ms);//更快出现死锁(如果有的话)
		std::unique_lock<std::mutex>lk_r(chopsticks[pid % philosopher_num], std::defer_lock);//取右边的筷子
        std::lock(lk_l, lk_r);
		cout << "哲学家" << pid << " 线程id" << std::this_thread::get_id() << "吃饭了" << endl;
	}
}

解决的情况2

只允许4位哲学家同时吃饭

int eating_num = 0;
std::mutex can_eat;
std::condition_variable num_eating;

void Philosopher(int pid) {
    while (true) {
        //能否吃饭
        std::unique_lock<std::mutex>lk_e(can_eat);
        num_eating.wait(lk_e, []() {return eating_num < philosopher_num - 1; });
        eating_num++;
        lk_e.unlock();

        std::unique_lock<std::mutex>lk_l(chopsticks[pid - 1]);//取左边的筷子
        std::this_thread::sleep_for(100ms);//更快出现死锁(如果有的话)
        std::unique_lock<std::mutex>lk_r(chopsticks[pid % philosopher_num]);//取右边的筷子
        cout << "哲学家" << pid << " 线程id" << std::this_thread::get_id() << "吃饭了" << endl;

        lk_e.lock();
        eating_num--;
        lk_e.unlock();
        num_eating.notify_all();
    }
}

解决的情况3

奇数哲学家先拿左边的筷子,偶数哲学家先拿右边筷子。这种方法思想和实现上最简单,不需要使用别的技术。

void Philosopher(int pid){
    while (true) {
        cout << pid - 1 << endl;
        if (pid % 2 == 0) {
            std::unique_lock<std::mutex>lk_l(chopsticks[pid - 1]);//取左边的筷子
            std::this_thread::sleep_for(100ms);//更快出现死锁(如果有的话)
            std::unique_lock<std::mutex>lk_r(chopsticks[pid % philosopher_num]);//取右边的筷子
        }
        else {
            std::unique_lock<std::mutex>lk_r(chopsticks[pid % philosopher_num]);//取右边的筷子
            std::this_thread::sleep_for(100ms);//更快出现死锁(如果有的话)
            std::unique_lock<std::mutex>lk_l(chopsticks[pid - 1]);//取左边的筷子
        }

        cout << "哲学家"<<pid<<" 线程id" << std::this_thread::get_id() <<"吃饭了" << endl;
    }
}

使用C++11的锁机制解决哲学家吃饭问题太简单了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值