在C中使用带有pthreads的全局结构
我试图模拟客户进入银行,并在一段时间内接受出纳员的服务。我使用一个线程来确定客户是否通过到达率进入银行,并使用多个线程来表示具有s服务率的出纳员。我使用struct来保存时间段、到达率、服务率、出纳员数量和客户等待队列。我试图在所有线程之间共享该结构,但出现“取消引用指针”错误和“请求非结构中的成员x”错误 信息通过从命令行传递到结构中在C中使用带有pthreads的全局结构,c,multithreading,struct,pthreads,simulation,C,Multithreading,Struct,Pthreads,Simulation,我试图模拟客户进入银行,并在一段时间内接受出纳员的服务。我使用一个线程来确定客户是否通过到达率进入银行,并使用多个线程来表示具有s服务率的出纳员。我使用struct来保存时间段、到达率、服务率、出纳员数量和客户等待队列。我试图在所有线程之间共享该结构,但出现“取消引用指针”错误和“请求非结构中的成员x”错误 信息通过从命令行传递到结构中 struct shiftInfo *Q = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)
struct shiftInfo *Q = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
struct shiftInfo info;
info.simTime = atoi(argv[1]);
info.arrivalRate = atof(argv[2]);
info.tellers = atoi(argv[3]);
info.serviceTime = atoi(argv[4]);
info.sampleInterval = atoi(argv[5]);
//Initiates Q to 0
for (int i = 0; i < maxCust; i++)
info.Q[i] = 0;
为了简短起见,我将只询问计时器线程,并希望将答案应用于其他线程。计时器线程通过以下方式在主线程中创建:
int status;
struct shiftInfo *I = info;
pthread_t time;
status = pthread_create(&time, NULL, timer, (void *)info);
if (status){
printf("ERROR CODE: %d\n", status);
exit(-1);
}
定时器线程函数为:
void *timer(void *info){
int timeRemaining = info -> simTime;
while(timeRemaining){
sleep(1);
timeRemaining--;
}
}
对于“int timeRemaining=info->simTime;”,我得到了警告“取消引用void指针”和对成员–simTime–的错误请求,它们不是结构或联合。
任何建议都将不胜感激
此外,我创建客户线程的方式与创建计时器线程的方式相同,但收到了一个警告(警告:传递参数3–pthread_create–makes pointer from integer而不使用强制转换[默认情况下启用]),而我在创建任何其他线程时没有收到该警告,这是什么原因造成的
pthread_t customer;
status = pthread_create(&customer, NULL, customer, (void *)info);
if (status){
printf("ERROR CODE: %d\n", status);
exit(-1);
}
这个片段有问题:
struct shiftInfo *Q = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
struct shiftInfo info;
info.simTime = atoi(argv[1]);
info.arrivalRate = atof(argv[2]);
info.tellers = atoi(argv[3]);
info.serviceTime = atoi(argv[4]);
info.sampleInterval = atoi(argv[5]);
//Initiates Q to 0
for (int i = 0; i < maxCust; i++)
info.Q[i] = 0;
现在,您可以使用shift
(或您选择的任何名称)设置全局指针。请注意,不能将具有灵活数组成员的结构作为全局变量(指向它们的全局指针-是;全局变量-否),也不能将它们作为自动变量。问题是您无法为这样的灵活数组成员分配任何空间
您需要考虑如何控制对多个线程的全局结构的访问,以及对全局结构的序列化访问是否会成为严重的瓶颈。您可能需要一个互斥锁,可能还需要一些条件
至于您的计时器
代码:您需要转换传递到结构ShiftInfo*
的void*
void *timer(void *vp)
{
struct ShiftInfo *info = vp;
int timeRemaining = info->simTime;
while(timeRemaining){
sleep(1);
timeRemaining--;
}
return 0;
}
请注意,您确实需要从函数返回一个值。此外,你需要考虑这是否会实现你想要的。它有一个已更改的局部变量。您可能需要将info
中的值设置为剩余时间。这需要每个操作都有互斥访问。我假设您添加并初始化了一个额外的成员:
pthread_t mutex;
到您的结构shiffinfo
void *timer(void *vp)
{
struct shiftInfo *info = vp;
if (pthread_mutex_lock(&info->mutex) != 0)
return 0; // Report error before returning?
int *timeRemaining = &info->simTime;
while (*timeRemaining > 0)
{
if (pthread_mutex_unlock(&info->mutex) != 0)
return 0; // Report error before returning?
sleep(1);
if (pthread_mutex_lock(&info->mutex) != 0)
return 0; // Report error before returning?
(*timeRemaining)--;
}
if (pthread_mutex_unlock(&info->mutex) != 0)
return 0; // Report error before returning?
return 0;
}
你犯了不少错误和打字错误。第一个错误是:
struct shiftInfo *Q = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
struct shiftInfo info;
info.simTime = atoi(argv[1]);
info.arrivalRate = atof(argv[2]);
info.tellers = atoi(argv[3]);
info.serviceTime = atoi(argv[4]);
info.sampleInterval = atoi(argv[5]);
//Initiates Q to 0
for (int i = 0; i < maxCust; i++)
info.Q[i] = 0;
void *timer(void *info){
int timeRemaining = info -> simTime;
下一个错误是:
status = pthread_create(&time, NULL, timer, (void *)info);
在代码中,info
是一个结构。但你正试图把它投射到一个指针上。如果您使用我上面建议的修复方法,info
将是一个指针,您可以保持此代码不变。您需要确保对pthread\u create
pass(void*)info
,而不是(void*)info
void *timer(void *vp)
{
struct shiftInfo *info = vp;
if (pthread_mutex_lock(&info->mutex) != 0)
return 0; // Report error before returning?
int *timeRemaining = &info->simTime;
while (*timeRemaining > 0)
{
if (pthread_mutex_unlock(&info->mutex) != 0)
return 0; // Report error before returning?
sleep(1);
if (pthread_mutex_lock(&info->mutex) != 0)
return 0; // Report error before returning?
(*timeRemaining)--;
}
if (pthread_mutex_unlock(&info->mutex) != 0)
return 0; // Report error before returning?
return 0;
}
最后一个错误是:
struct shiftInfo *Q = malloc(sizeof(struct shiftInfo) + (maxCust*sizeof(int)));
struct shiftInfo info;
info.simTime = atoi(argv[1]);
info.arrivalRate = atof(argv[2]);
info.tellers = atoi(argv[3]);
info.serviceTime = atoi(argv[4]);
info.sampleInterval = atoi(argv[5]);
//Initiates Q to 0
for (int i = 0; i < maxCust; i++)
info.Q[i] = 0;
void *timer(void *info){
int timeRemaining = info -> simTime;
请尝试以下方法:
void *timer(void *arg){
struct shiftInfo *info = (struct shiftInfo *) arg;
int timeRemaining = info -> simTime;
在timer()函数中,必须将info参数从(void*)强制转换为(struct shiftInfo*)
另外,在创建客户时,应该是这样的
status = pthread_create(&customer, NULL, customer, (void *)&info);
谢谢你的回复,我做了建议的更改,正如现在在这篇文章中看到的,但是我仍然收到类似的错误和警告。另外,我也不太担心对结构的访问,因为唯一改变的方面是计时器和客户Q,尽管我不知道如何确保两个出纳员不尝试获取相同的客户。通过确保线程访问数据结构时的互斥,可以确保两个出纳员不尝试获取相同的客户。您可以设计具有多个互斥体的方案来控制对结构不同部分的访问,但最低要求是一个互斥体。对于访问全局变量的多线程应用程序,您必须非常小心。谢谢,我要补充的是,一旦我启动并运行了核心代码,我不认为这会导致问题,因为这更像是一个错误的结果错误,而不是编译器问题。谢谢,我提出了您的前两个更改建议,正如现在在文章中看到的,但是对void*timer的更改似乎使simTime成为一个局部变量,我希望计时器对simTime所做的更改能够从所有线程读取。根本不要使用
timeRemaining
。只需使用info->simTime
。对info->simTime
的任何更改都应该对所有线程可见,因为您在pthread\u create
中向每个线程传递了相同的info
。您是否建议使用类似于“void*timer(void*arg){struct shiftInfo*info=(struct shiftInfo*)arg而(info->simTime){sleep(1);(info->simTime)}“这似乎消除了那一节中的错误,但我还有原帖中提到的其他错误@JS1I只是在学习多线程,有几个动态分配的数组需要传递给每个pthread。这个答案真的帮助我简化了代码,避免了重复不必要的数据。您关于timeRemaining的建议导致了错误“error:info–undeclared(首次在这个函数中使用)int-timeRemaining=((struct-shiftInfo*)info)->simTime;”,这难道不会使timeRemaining成为一个局部变量吗?我希望它可以从所有线程访问。另外,为什么不能像计时器功能一样将客户声明为“void*customer(void*info)”?对不起,当我阅读您的回复时,我显然非常累,感谢@Phuc-Nguyen V的建议。请不要改变问题,使答案无效!抱歉,我正在尝试用答案更新它以避免重复,我会将其更改回。
int timeRemaining = ((struct shiftInfo *)info) -> simTime;
status = pthread_create(&customer, NULL, customer, (void *)&info);