【发布时间】:2022-12-22 05:27:02
【问题描述】:
我的程序使用枚举作为信号量。有两种可能的值/状态(因为它是二进制信号量)。该程序编译正常。 signal() 和 wait() 看起来合乎逻辑。为什么程序行为如此不可预测?即使是整数 printf 也是错误的。这是代码:
#include <stdio.h>
#include <pthread.h>
typedef enum {IN_USE,NOT_IN_USE} binary_semaphore;
binary_semaphore s=NOT_IN_USE;
struct parameters{
int thread_num;
};
void wait(){
while(s==IN_USE);
s=IN_USE;
}
void signal(){
s=NOT_IN_USE;
}
void resource(void *params){
//assuming parameter is a parameters struct.
struct parameters *p=(struct parameters*)params;
wait();
printf("Resource is being used by thread %d\n",(*p).thread_num);
signal();
}
int main(void){
pthread_t threads[4];
struct parameters ps[4]={{1},{2},{3},{4}};
register int counter=0;
while(counter++<4){
pthread_create(&threads[counter],NULL,resource,(void*)&ps[counter]);
}
return 0;
}
我的代码有什么问题? 一些输出(是的,每次都不同):-
(NOTHING)
Resource is being used by thread 32514
Resource is being used by thread 0
Resource is being used by thread 0
Resource is being used by thread 32602
Resource is being used by thread -24547608
是不是垃圾值问题?
【问题讨论】:
-
需要访问您的
binary_semaphore原子并使用其他同步原语来锁定对它的访问。现在您将遇到数据争用和未定义的行为。 -
作为一个典型的例子:如果两个线程等待信号量会怎样。第三个线程向它发出信号,第一个等待的线程退出循环。但是在它可以将其标记为正在使用之前,它被第二个等待线程抢占了。第二个等待线程退出循环并将其标记为正在使用。当第一个等待线程再次启动时,它将还将其标记为正在使用。现在你有二认为可以继续的线程,当它不是。您拥有的线程越多,这个问题就越严重。
-
简而言之:不要创建自己的线程原语,使用已经存在的。
-
另一方面,
register说明符如今确实没有实际意义,除了您不能使用指向&运算符的指针获取此类变量的地址。编译器比我们任何人都更能决定什么应该进入寄存器或不进入寄存器。此外,通过使用普通的for循环,该循环会更容易阅读和理解:for (unsigned counter = 0; counter < 4; ++counter) { ... } -
即时的问题是你的“聪明”while循环.别耍小聪明了,用
for。它存在的理由很充分。不信,就在循环里面打印i的值。
标签: c enums pthreads semaphore garbage