posix信号量以及互斥量实现哲学家就餐问题

posix信号量以及互斥量实现哲学家就餐问题

1.哲学家就餐问题描述(请参考请参考其他博主)
2.如何实现就餐场景
a.5个信号量代表5支筷子
b.5五个线程代表5个哲学家
c.主线程负责创建筷子们和哲学家们
d.sem_wait函数 模拟拿筷子
3.可能出现同时拿筷子的情况,这时哲学家们依次等待
4.解决方案之一,让其中一人反向拿筷子(程序中为第五个)
5.同理,将信号量的创建和使用改成互斥量即可实现互斥量实现哲学家就餐问题模拟

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>
sem_t sem[5];

void err_pthread(int ret, char *str)
{
        if(ret != 0)
        {
                fprintf(stderr,"%s:%s\n",str,strerror(ret));
                //pthread_exit(NULL);
                exit(1);
        }
}
void sys_err(char *str)
{
        perror(str);
        exit(1);
}
#define DELAY (sleep(rand() % 3))
void *thread_func(void *arg)
{
        long i = (long) arg;

        while(1)
        {
               /*解决方法 
               if (i == 4)
                {
                        printf("thread No.%ld thinking\n",i+1);
                        DELAY ;
                        printf("thread No.%ld hungry\n",i+1);
                        sem_wait(&sem[(i+1 ) % 5]);
                        DELAY ;
                        sem_wait(&sem[i]);
                        printf("thread No.%ld eating\n",i+1);
                        DELAY ;
                        sem_post(&sem[i]);
                        sem_post(&sem[(i+1 ) % 5]);
                        DELAY ;
                }
                else {*/
                        printf("thread No.%ld thinking\n",i+1);
                        DELAY ;
                        printf("thread No.%ld hungry\n",i+1);
                        sem_wait(&sem[i]);拿左筷子
                        DELAY ;
                        sem_wait(&sem[(i+1 ) % 5]);拿右筷子
                        printf("thread No.%ld eating\n",i+1);
                        DELAY ;
                        sem_post(&sem[(i+1 ) % 5]);
                        sem_post(&sem[i]);
                        DELAY ;
                //}

        }
        
        return NULL;
}
int main(void) 
{
        long i;
        int ret;
        pthread_t tid[5];
        //init sem and threads
        //创建 信号量和线程
        for(i = 0; i<5;i++)
        {
               ret = sem_init(&sem[i], 0, 1);
               if(ret != 0)
                       sys_err("mutex init");
        }
        for(i=0; i<5; i++)
        {
               ret = pthread_create(&tid[i], NULL, thread_func, (void *) i);
               if(ret != 0)
                       err_pthread(ret, "thread_create");
        //       printf("tid[%ld] = %lu\n",i,tid[i]);
        }
//信号量销毁和线程回收
        for(i=0;i<5;i++)
        {
                int r;
                r=pthread_join(tid[i],NULL);
                if (r!=0)
                        printf("failed join!\n");
                else
                        printf("thread No.%ld\n",i);
        }
        for(i = 0;i<5;i++)
        {
                sem_destroy(&sem[i]);
                printf("%ld had been destoyed\n",i);
        }
        return 0;
}
好的,我会尽力回答你的问题。首先,哲学家进餐问题是一个经典的多线程同步问题,其描述如下: 有五位哲学家,围坐在一张圆桌周围,他们的生活方式只有思考和进餐。在圆桌上有五个餐具,每两个相邻的哲学家之间放置一把餐叉。哲学家进餐时需要同时拿到他左右两个餐叉,才能进餐。当一个哲学家进餐结束后,他会放下手中的餐叉,然后继续思考。请设计一个程序,使得每个哲学家都能够进餐,但不会出现死锁或饥饿状态。 在Linux系统中,我们可以使用POSIX API实现多线程互斥机制。具体来说,我们可以使用pthread_create函数创建多个线程,每个线程代表一个哲学家。在每个线程中,我们可以使用pthread_mutex_lock和pthread_mutex_unlock函数来实现互斥机制,保证每个哲学家在进餐时只能同时拿到他左右两个餐叉。 下面是一个基于POSIX API哲学家进餐问题的代码实现: ```c #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define NUM_PHILOSOPHERS 5 #define LEFT (i + NUM_PHILOSOPHERS - 1) % NUM_PHILOSOPHERS #define RIGHT (i + 1) % NUM_PHILOSOPHERS pthread_mutex_t chopstick[NUM_PHILOSOPHERS]; void *philosopher(void *arg) { int i = *(int *)arg; while (1) { printf("Philosopher %d is thinking...\n", i); sleep(rand() % 5); printf("Philosopher %d is hungry...\n", i); pthread_mutex_lock(&chopstick[LEFT]); pthread_mutex_lock(&chopstick[RIGHT]); printf("Philosopher %d is eating...\n", i); sleep(rand() % 5); pthread_mutex_unlock(&chopstick[RIGHT]); pthread_mutex_unlock(&chopstick[LEFT]); } return NULL; } int main() { pthread_t tid[NUM_PHILOSOPHERS]; int i, id[NUM_PHILOSOPHERS]; for (i = 0; i < NUM_PHILOSOPHERS; ++i) { pthread_mutex_init(&chopstick[i], NULL); } for (i = 0; i < NUM_PHILOSOPHERS; ++i) { id[i] = i; pthread_create(&tid[i], NULL, philosopher, &id[i]); } for (i = 0; i < NUM_PHILOSOPHERS; ++i) { pthread_join(tid[i], NULL); } for (i = 0; i < NUM_PHILOSOPHERS; ++i) { pthread_mutex_destroy(&chopstick[i]); } return 0; } ``` 在这个程序中,我们首先定义了一个长度为5的互斥数组,用于表示五个餐叉。然后,我们使用pthread_create函数创建了五个线程,每个线程代表一个哲学家。在每个线程中,我们使用pthread_mutex_lock和pthread_mutex_unlock函数来实现互斥机制,保证每个哲学家在进餐时只能同时拿到他左右两个餐叉。最后,我们使用pthread_join函数等待所有线程结束,并释放互斥资源。 希望这个代码可以帮助你理解如何利用POSIX API在Linux系统上,通过多线程互斥机制实现哲学家进餐问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

фора 快跑

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

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

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

打赏作者

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

抵扣说明:

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

余额充值