C将数组传递给在饮食哲学家中的pthread

时间:2017-05-09 20:36:17

标签: c arrays pthreads

我正在为用户输入的N个哲学家编写Dining Philosopher线程问题的代码。解除引用void *指针时出错。传递数组时我做错了什么?

 void *philosopher(void *arg_l);

 int main()
 {   
     int i,A,B;
     scanf("%10d", &A);
     scanf("%10d", &B);
     printf("You got %d phils and %d turns each\n",A,B);

     int args[2];
     args[0] = A;
     args[1] = B;

     pthread_t thread_id[A];
     sem_init(&mutex,0,1);
     for(i=0;i<A;i++)
         sem_init(&S[i],0,0);
     for(i=0;i<A;i++)
     {
         args[2] = phil_num[i];
         pthread_create(&thread_id[i],NULL,philosopher,&args);
         printf("Philosopher %d is thinking\n",i+1);
     }
     for(i=0;i<A;i++)
         pthread_join(thread_id[i],NULL);
}

void *philosopher(void *arg_l)
{
    arg_l[0] = int A;
    arg_l[1] = int B;
    ...
    return NULL;
}

2 个答案:

答案 0 :(得分:1)

由于arg_l的类型为void *,因此您无法在其上使用下标运算符[]。这意味着每个元素都有void类型,无法实例化。此外,赋值右侧的语法无效。

您需要先将线程参数强制转换为int *,然后才能使用它。此外,您需要传入args而不使用其地址,因为数组在传递给函数时会衰减为指向第一个元素的指针。

pthread_create(&thread_id[i],NULL,philospher,args);

...

void *philospher(void *arg_l)
{
     int *args = arg_l;
     ...

}

答案 1 :(得分:0)

您的行如:

arg_l[0] = int A;

完全坏了。你会逃脱:

int A = ((int *)arg_l)[0];

你不能有效取消引用void *,也不能将它们编入索引(部分因为这需要解除引用,部分原因是在标准C中 - 而不是GNU C - sizeof(void)未定义)。您需要转换为具有强制转换的适当类型,然后进行derefence,如图所示。

注意:args[2] = phil_num[i];写出界限(您定义int args[2];但似乎需要int args[3];

您必须为每个哲学家传递一个单独的数组,因为无法保证给定的线程在主线程重新分配新值之前读取信息。通常,您将使用结构而不是数组来传递给单个线程的数据;你有一个这些结构的初始化数组,以便每个线程获得自己独特的控制信息。

  

有什么办法可以举一个例子吗?

有点像这样。关键点是struct Info的数组,每个数组都是单独初始化的(使用C99复合文字),并且数组的不同元素被传递给每个线程,以便它获取自己的数据,而不是尝试与其他线程共享数据。

#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>

#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

struct Info
{
    int number;
    int turns;
    int diner;
};

enum { MAX_PHILOSOPHERS = 10 };
enum { MAX_TURNS = 99 };
static sem_t mutex;
static sem_t S[MAX_PHILOSOPHERS];
static void *philosopher(void *arg_l);

int main(void)
{
    int A, B;
    printf("How many philosophers? How many turns? ");
    fflush(stdout);
    if (scanf("%d %d", &A, &B) != 2)
    {
        fprintf(stderr, "Failed to read input\n");
        return 1;
    }
    if (A < 2)
        fprintf(stderr, "You specified too few philosophers (%d)\n", A);
    if (A > MAX_PHILOSOPHERS)
        fprintf(stderr, "You specified too many philosophers (%d, but the maximum is %d)\n",
                A, MAX_PHILOSOPHERS);
    if (B < 1)
        fprintf(stderr, "You specified too few turns (%d)\n", B);
    if (B > MAX_TURNS)
        fprintf(stderr, "You specified too many turns (%d, but the maximum is %d)\n",
                B, MAX_TURNS);
    if (A < 2 || A > MAX_PHILOSOPHERS || B < 1 || B > MAX_TURNS)
        return 1;
    printf("You have %d philosophers who get %d turns each\n", A, B);

    /* This assignment could be in the thread creation loop before pthread_create() */
    /* Or in the loop that uses sem_init() */
    struct Info info[A];
    for (int i = 0; i < A; i++)
        info[i] = (struct Info){ A, B, i};

    sem_init(&mutex, 0, 1);
    for (int i = 0; i < A; i++)
        sem_init(&S[i], 0, 0);

    pthread_t thread_id[A];
    for (int i = 0; i < A; i++)
    {
        pthread_create(&thread_id[i], NULL, philosopher, &info[i]);
        printf("Philosopher %d is thinking\n", i + 1);
    }

    for (int i = 0; i < A; i++)
        pthread_join(thread_id[i], NULL);

    printf("Dinner is over\n");
    return 0;
}

static void *philosopher(void *arg_l)
{
    struct Info *info = arg_l;
    printf("N = %d, T = %d, I = %d\n", info->number, info->turns, info->diner);
    /* ...do dining stuff; remember to share nicely!... */
    return 0;
}

#pragma允许代码在macOS Sierra上编译,它没有<semaphore.h>函数的工作版本 - 它们只返回错误指示并将errno设置为ENOSYS(功能未实施)。 这段代码应该检查pthread函数和信号量操作的返回值 - 它是懒惰的不这样做。