我正在为用户输入的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;
}
答案 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函数和信号量操作的返回值 - 它是懒惰的不这样做。