哲学家就餐问题--互斥锁

哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。他们只能使用自己左右手边的那两只餐叉。哲学家就餐问题有时也用米饭和筷子而不是意大利面和餐叉来描述,因为很明显,吃米饭必须用两根筷子。
哲学家从来不交谈,这就很危险,可能产生死锁,每个哲学家都拿着左手的餐叉,永远都在等右边的餐叉(或者相反)。即使没有死锁,也有可能发生资源耗尽。例如,假设规定当哲学家等待另一只餐叉超过五分钟后就放下自己手里的那一只餐叉,并且再等五分钟后进行下一次尝试。这个策略消除了死锁(系统总会进入到下一个状态),但仍然有可能发生“活锁”。**如果五位哲学家在完全相同的时刻进入餐厅,并同时拿起左边的餐叉,那么这些哲学家就会等待五分钟,同时放下手中的餐叉,再等五分钟,又同时拿起这些餐叉。**为了解决这个几率极小的可能性,我们可以让其中一个哲学家不按常理出牌。下面会说明这个问题的解决方法。

在实际的计算机问题中,缺乏餐叉可以类比为缺乏共享资源。一种常用的计算机技术是资源加锁,用来保证在某个时刻,资源只能被一个程序或一段代码访问。当一个程序想要使用的资源已经被另一个程序锁定,它就等待资源解锁。当多个程序涉及到加锁的资源时,在某些情况下就有可能发生死锁。例如,某个程序需要访问两个文件,当两个这样的程序各锁了一个文件,那它们都在等待对方解锁另一个文件,而这永远不会发生。

在这里插入图片描述
在这里插入图片描述
五个哲学家,五只筷子,右手边的是自己的筷子,左手边是其他人的筷子,为了解决死锁问题,可以让哲学家E先用右手抢别人的筷子,然后再拿自己的筷子,这样那个问题就解决了。

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
pthread_mutex_t mutex[5];

void* dinner(void* arg)
{
    int num = (int)arg;
    int left,right;
    if(num < 4){
        //前四个人右手拿自己筷子
        right = num;
        left = right + 1;
    }
    else if(num == 4){
        //最后一个人左手拿自己筷子
        right = 0;
        left = num;
    }
    while(1){
        //右手加锁
        pthread_mutex_lock(&mutex[right]);
        //左手尝试加锁
        if(pthread_mutex_trylock(&mutex[left]) == 0){
            //吃面
            printf("%c 正在吃面。。。。。。\n", num+'A');
            //左手解锁
            pthread_mutex_unlock(&mutex[left]);
        }
        //右手解锁
        pthread_mutex_unlock(&mutex[right]);
        sleep(rand() % 5);
    }
}
int main()
{
    pthread_t p[5];
    //init
    for(int i = 0;i < 5;i++) pthread_mutex_init(&mutex[5],NULL);
    //create
    for(int i = 0;i < 5;i++) pthread_create(&p[i],NULL,dinner,(void*)i);
    //join
    for(int i = 0;i < 5;i++) pthread_join(p[i],NULL);
    //destroy
    for(int i = 0;i < 5;i++) pthread_mutex_destroy(&mutex[i]);
    return 0;
}

编译的时候记得加上库
gcc xxx.c -o xxx -lpthread

感谢点赞!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值