Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用pthread、互斥锁和条件变量解决问题_C_Pthreads_Mutex_Condition Variable_Dining Philosopher - Fatal编程技术网

C 使用pthread、互斥锁和条件变量解决问题

C 使用pthread、互斥锁和条件变量解决问题,c,pthreads,mutex,condition-variable,dining-philosopher,C,Pthreads,Mutex,Condition Variable,Dining Philosopher,我试图使用pthread、互斥锁和条件变量在C中实现这个问题。 它需要一个命令行参数来指定程序应该运行多长时间。我必须使用睡眠功能来完成这项任务 每个哲学家最多可以吃10顿饭。一旦达到10次,pthread应该终止 在设定的时间量结束时,pthread需要终止,并且应该打印每个线程吃的食物数 我的输出有一些问题: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <

我试图使用pthread、互斥锁和条件变量在C中实现这个问题。

  • 它需要一个命令行参数来指定程序应该运行多长时间。我必须使用睡眠功能来完成这项任务
  • 每个哲学家最多可以吃10顿饭。一旦达到10次,pthread应该终止
  • 在设定的时间量结束时,pthread需要终止,并且应该打印每个线程吃的食物数
我的输出有一些问题:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

//Function declarations
void *pickup_forks(void * philosopher_number);
void *return_forks(void * philosopher_number);
void test(int philosopher_number);
int left_neighbor(int philosopher_number);
int right_neighbor(int philosopher_number);
double think_eat_time(void);
void think(double think_time);
void eat(double eat_time);

//Constants to be used in the program.
#define PHILOSOPHER_NUM 5
#define MAX_MEALS 10
#define MAX_THINK_EAT_SEC 3

//States of philosophers.
enum {THINKING, HUNGRY, EATING} state[PHILOSOPHER_NUM];

//Array to hold the thread identifiers.
pthread_t philos_thread_ids[PHILOSOPHER_NUM];

//Mutex lock.
pthread_mutex_t mutex;

//Condition variables.
pthread_cond_t cond_vars[PHILOSOPHER_NUM];

//Array to hold the number of meals eaten for each philosopher.
int meals_eaten[PHILOSOPHER_NUM];

int main(int argc, char *argv[])
{
    //Ensure correct number of command line arguments.
    if(argc != 2)
    {
        printf("Please ensure that the command line argument 'run_time' is passed.\n");
    }
    else
    {
        //Set command line argument value to variable run_time;
        double run_time = atof(argv[1]);

        //Initialize arrays.
        int i;
        for(i = 0; i < PHILOSOPHER_NUM; i++)
        {
            state[i] = THINKING;
            pthread_cond_init(&cond_vars[i], NULL);
            meals_eaten[i] = 0;
        }


        //Initialize the mutex lock.
        pthread_mutex_init(&mutex, NULL);

        //Join the threads.
        for(i = 0; i < PHILOSOPHER_NUM; i++)
        {
            pthread_join(philos_thread_ids[i], NULL);
        }

        //Create threads for the philosophers.
        for(i = 0; i < PHILOSOPHER_NUM; i++)
        {
            pthread_create(&philos_thread_ids[i], NULL, pickup_forks, (void *)&i);
        }

        sleep(run_time);

        for(i = 0; i < PHILOSOPHER_NUM; i++)
        {
            pthread_cancel(philos_thread_ids[i]);
        }

        //Print the number of meals that each philosopher ate.
        for(i = 0; i < PHILOSOPHER_NUM; i++)
        {
            printf("Philosopher %d: %d meals\n", i, meals_eaten[i]);
        }

    }

    return 0;
}

void *pickup_forks(void * philosopher_number)
{
    int loop_iterations = 0;
    int pnum = *(int *)philosopher_number;

    while(meals_eaten[pnum] < MAX_MEALS)
    {
        printf("Philosoper %d is thinking.\n", pnum);
        think(think_eat_time());

        pthread_mutex_lock(&mutex);
        state[pnum] = HUNGRY;
        test(pnum);

        while(state[pnum] != EATING)
        {
            pthread_cond_wait(&cond_vars[pnum], &mutex);
        }
        pthread_mutex_unlock(&mutex);

        (meals_eaten[pnum])++;

        printf("Philosoper %d is eating meal %d.\n", pnum, meals_eaten[pnum]);
        eat(think_eat_time());

        return_forks((philosopher_number));

        loop_iterations++;
    }
}

void *return_forks(void * philosopher_number)
{
    pthread_mutex_lock(&mutex);
    int pnum = *(int *)philosopher_number;

    state[pnum] = THINKING;

    test(left_neighbor(pnum));
    test(right_neighbor(pnum));

    pthread_mutex_unlock(&mutex);
}

int left_neighbor(int philosopher_number)
{
    return ((philosopher_number + (PHILOSOPHER_NUM - 1)) % 5);
}

int right_neighbor(int philosopher_number)
{
    return ((philosopher_number + 1) % 5);
}

void test(int philosopher_number)
{
    if((state[left_neighbor(philosopher_number)] != EATING) && 
        (state[philosopher_number] == HUNGRY) &&
        (state[right_neighbor(philosopher_number)] != EATING))
    {
        state[philosopher_number] = EATING;
        pthread_cond_signal(&cond_vars[philosopher_number]);
    }
}

double think_eat_time(void)
{
    return ((double)rand() * (MAX_THINK_EAT_SEC - 1)) / (double)RAND_MAX + 1;
}

void think(double think_time)
{
    sleep(think_time);
}

void eat(double eat_time)
{
    sleep(eat_time);
}
~$ gcc dining_philos.c -o dp -lpthread
~$ ./dp 10
Philosoper 1 is thinking.
Philosoper 2 is thinking.
Philosoper 3 is thinking.
Philosoper 4 is thinking.
Philosoper 5 is thinking.
Philosoper 2 is eating meal 1.
Philosoper 4 is eating meal 1.
Philosoper 2 is thinking.
Philosoper 4 is thinking.
Philosoper 2 is eating meal 2.
Philosoper 4 is eating meal 4.
Philosoper 4 is thinking.
Philosoper 2 is thinking.
Philosoper 2 is eating meal 3.
Philosoper 4 is eating meal 5.
Philosoper 2 is thinking.
Philosoper 4 is thinking.

Philosopher 0: 2 meals
Philosopher 1: 0 meals
Philosopher 2: 3 meals
Philosopher 3: 0 meals
Philosopher 4: 5 meals
  • 在命令行中输入的秒数使主函数休眠似乎并没有使输出有所不同
  • 大多数哲学家都对程序的大部分执行感到饥饿
  • 当我打印出一个哲学家在思考或吃饭的时候,一个“哲学家5”出现了,尽管应该只有哲学家0-4
  • 这是我的代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pthread.h>
    
    //Function declarations
    void *pickup_forks(void * philosopher_number);
    void *return_forks(void * philosopher_number);
    void test(int philosopher_number);
    int left_neighbor(int philosopher_number);
    int right_neighbor(int philosopher_number);
    double think_eat_time(void);
    void think(double think_time);
    void eat(double eat_time);
    
    //Constants to be used in the program.
    #define PHILOSOPHER_NUM 5
    #define MAX_MEALS 10
    #define MAX_THINK_EAT_SEC 3
    
    //States of philosophers.
    enum {THINKING, HUNGRY, EATING} state[PHILOSOPHER_NUM];
    
    //Array to hold the thread identifiers.
    pthread_t philos_thread_ids[PHILOSOPHER_NUM];
    
    //Mutex lock.
    pthread_mutex_t mutex;
    
    //Condition variables.
    pthread_cond_t cond_vars[PHILOSOPHER_NUM];
    
    //Array to hold the number of meals eaten for each philosopher.
    int meals_eaten[PHILOSOPHER_NUM];
    
    int main(int argc, char *argv[])
    {
        //Ensure correct number of command line arguments.
        if(argc != 2)
        {
            printf("Please ensure that the command line argument 'run_time' is passed.\n");
        }
        else
        {
            //Set command line argument value to variable run_time;
            double run_time = atof(argv[1]);
    
            //Initialize arrays.
            int i;
            for(i = 0; i < PHILOSOPHER_NUM; i++)
            {
                state[i] = THINKING;
                pthread_cond_init(&cond_vars[i], NULL);
                meals_eaten[i] = 0;
            }
    
    
            //Initialize the mutex lock.
            pthread_mutex_init(&mutex, NULL);
    
            //Join the threads.
            for(i = 0; i < PHILOSOPHER_NUM; i++)
            {
                pthread_join(philos_thread_ids[i], NULL);
            }
    
            //Create threads for the philosophers.
            for(i = 0; i < PHILOSOPHER_NUM; i++)
            {
                pthread_create(&philos_thread_ids[i], NULL, pickup_forks, (void *)&i);
            }
    
            sleep(run_time);
    
            for(i = 0; i < PHILOSOPHER_NUM; i++)
            {
                pthread_cancel(philos_thread_ids[i]);
            }
    
            //Print the number of meals that each philosopher ate.
            for(i = 0; i < PHILOSOPHER_NUM; i++)
            {
                printf("Philosopher %d: %d meals\n", i, meals_eaten[i]);
            }
    
        }
    
        return 0;
    }
    
    void *pickup_forks(void * philosopher_number)
    {
        int loop_iterations = 0;
        int pnum = *(int *)philosopher_number;
    
        while(meals_eaten[pnum] < MAX_MEALS)
        {
            printf("Philosoper %d is thinking.\n", pnum);
            think(think_eat_time());
    
            pthread_mutex_lock(&mutex);
            state[pnum] = HUNGRY;
            test(pnum);
    
            while(state[pnum] != EATING)
            {
                pthread_cond_wait(&cond_vars[pnum], &mutex);
            }
            pthread_mutex_unlock(&mutex);
    
            (meals_eaten[pnum])++;
    
            printf("Philosoper %d is eating meal %d.\n", pnum, meals_eaten[pnum]);
            eat(think_eat_time());
    
            return_forks((philosopher_number));
    
            loop_iterations++;
        }
    }
    
    void *return_forks(void * philosopher_number)
    {
        pthread_mutex_lock(&mutex);
        int pnum = *(int *)philosopher_number;
    
        state[pnum] = THINKING;
    
        test(left_neighbor(pnum));
        test(right_neighbor(pnum));
    
        pthread_mutex_unlock(&mutex);
    }
    
    int left_neighbor(int philosopher_number)
    {
        return ((philosopher_number + (PHILOSOPHER_NUM - 1)) % 5);
    }
    
    int right_neighbor(int philosopher_number)
    {
        return ((philosopher_number + 1) % 5);
    }
    
    void test(int philosopher_number)
    {
        if((state[left_neighbor(philosopher_number)] != EATING) && 
            (state[philosopher_number] == HUNGRY) &&
            (state[right_neighbor(philosopher_number)] != EATING))
        {
            state[philosopher_number] = EATING;
            pthread_cond_signal(&cond_vars[philosopher_number]);
        }
    }
    
    double think_eat_time(void)
    {
        return ((double)rand() * (MAX_THINK_EAT_SEC - 1)) / (double)RAND_MAX + 1;
    }
    
    void think(double think_time)
    {
        sleep(think_time);
    }
    
    void eat(double eat_time)
    {
        sleep(eat_time);
    }
    
    ~$ gcc dining_philos.c -o dp -lpthread
    ~$ ./dp 10
    Philosoper 1 is thinking.
    Philosoper 2 is thinking.
    Philosoper 3 is thinking.
    Philosoper 4 is thinking.
    Philosoper 5 is thinking.
    Philosoper 2 is eating meal 1.
    Philosoper 4 is eating meal 1.
    Philosoper 2 is thinking.
    Philosoper 4 is thinking.
    Philosoper 2 is eating meal 2.
    Philosoper 4 is eating meal 4.
    Philosoper 4 is thinking.
    Philosoper 2 is thinking.
    Philosoper 2 is eating meal 3.
    Philosoper 4 is eating meal 5.
    Philosoper 2 is thinking.
    Philosoper 4 is thinking.
    
    Philosopher 0: 2 meals
    Philosopher 1: 0 meals
    Philosopher 2: 3 meals
    Philosopher 3: 0 meals
    Philosopher 4: 5 meals
    

    我非常感谢您的帮助。谢谢

    pthread\u create将指针作为其最后一个参数传递。该指针必须在线程运行时有效,而不仅仅是在创建线程时有效。您正在使用一个指向循环变量i的指针,该变量已蒸发


    也不确定为什么在创建pthread_之前调用pthread_join,但我认为它会返回错误(您没有检查错误)。

    Ok。我创建了另一个保存哲学家编号的数组,并在pthread_create中为哲学家I传递了该数组的第I个索引。这似乎成功了。非常感谢。我不知道那是什么意思