哲学家用餐问题程序解决

1.问题描述:

一些哲学家围坐在圆桌旁,他们的两边都只有一根筷子。一般情况下他们都在思考着自己的问题,如果他们饿了,他们就需要吃饭,但是吃饭需要用一对筷子,即左右的两个筷子都得拿到手上才能开饭。

2.解决思路:

这是个很经典的同步问题,在这里可以把每个筷子和编号,若哲学家是i左边的筷子为i,右边的筷子是i+1,每个筷子都是一个独立的信号量置为1。若只按照这些条件设计程序运行,就会发现程序会很容易进入死锁状态,即每个哲学家都拿了一个筷子,这样谁都吃不上饭。为了解决死锁问题,有很多种方式。这里我采用了限制用餐人数来解决问题。把用餐人数的信号量设置为哲学家人数减1,就不会发生死锁了。

3.程序实现:

c++实现如下,编译时需加上 -lpthread

#include 
#include 
#include 
#include 
using namespace std;

const int num = 5; //设置哲学家的人数
sem_t chopstick[num], eatman; //创建筷子信号量和就餐人数上限信号量
typedef struct ThreadData {
    int id;
    int think;
    int eat;
} tdata; //线程的数据结构

void* philosopher(void* p) {
    int id = ((tdata*)p)->id;
    int think = ((tdata*)p)->think;
    int eat = ((tdata*)p)->eat;

    sleep(think);
    printf("philosopher %d: is thinking\n", id);

    sem_wait(&eatman);
    sem_wait(&chopstick[id]); //拿起左边的筷子
    sem_wait(&chopstick[(id + 1) % num]); //拿起右边的筷子
    sem_post(&eatman);

    printf("philosopher %d: start eating\n", id);
    sleep(eat); 
    printf("philosopher %d: end eating\n", id);

    sem_post(&chopstick[id]); //放下左边的筷子
    sem_post(&chopstick[(id + 1) % 5]); //放下右边的筷子
    pthread_exit(0);
    return NULL;
}

int main() {
    pthread_t tid[num]; //线程号初始化
    pthread_attr_t attr;
    pthread_attr_init(&attr); //线程属性初始化
    sem_init(&eatman, 0, num-1);
    for(int i = 0; i < num; i++) {
        sem_init(&chopstick[i], 0, 1); //初始化所有的筷子,信号量都为1
    }

    int thinklist[num] = {2, 6, 5, 3, 1};
    int eatlist[num] = {8, 3, 4, 5, 2}; //设置哲学家的思考时间和吃饭时间
    for(int id = 0; id < num; id++) {
        tdata* d = new tdata;
        d->id = id;
        d->think = thinklist[id];
        d->eat = eatlist[id];
        printf("create philosopher %d\n", id);
        pthread_create(&tid[id], &attr, philosopher, d); //创建哲学家线程
    }
    for(int i = 0; i < num; i++) {
        pthread_join(tid[i], NULL); //等待所有哲学家线程结束
    }

    sem_destroy(&eatman); //销毁信号量
    for(int i = 0; i < num; i++) {
        sem_destroy(&chopstick[i]); 
    }
    return 0;
}

4.运行结果:

create philosopher 0
create philosopher 1
create philosopher 2
create philosopher 3
create philosopher 4
philosopher 4: is thinking
philosopher 4: start eating
philosopher 0: is thinking
philosopher 0: start eating
philosopher 3: is thinking
philosopher 3: start eating
philosopher 4: end eating
philosopher 2: is thinking
philosopher 2: start eating
philosopher 1: is thinking
philosopher 1: start eating
philosopher 3: end eating
philosopher 2: end eating
philosopher 1: end eating
philosopher 0: end eating

你可能感兴趣的:(操作系统,c++,linux,算法)