C - 当其他线程修改值时,输出线程应更新



我有一个程序,它使用多线程进行一些计算并将结果添加到全局变量中。还有一个计数器,用于显示有多少线程已经完成,有多少线程仍在运行。线程已分离。除了这些线程之外,还有一个输出线程,用于识别另一个线程是否更改了这些全局变量之一。如果是这样,则应打印它们。输出线程也等待被动。

如何使输出线程等待全局值的更改?我可以做一段时间循环,直到所有线程完成并观察值的变化,但这不是我真正想要的。我希望输出线程被动等待。

sem_t sem;
int val1 = 0;
int val2 = 0;
int active = 0;
int finish = 0;
void* calc(void* arg){
sem_wait(&sem);
calculate(arg);
++finish;
sem_post(&sem);
return NULL;
}
void* out(void* arg){
//what to do here?
printf();
return NULL;
}
int main(int argc, char* argv[]){
pthread_t calcThread;
int somevalue;
sem_init(&sem, 0, argv[1]); // max amount of threads running simultaniously
for(int i = 2; i != argc; i++){
somevalue = atoi(argv[i]);
pthread_create(&calcThread, NULL, calc, &somevalue))
pthread_detach(calcThread);
}
}

为了达到使用信号量被动等待的行为,您需要 2 个信号量变量而不是一个。一个控制阅读,一个控制写作。让我们称呼它们:

sem_t read, write;

calc函数中,您需要等待读锁定被释放。sem_wait(&read);并在退出calc函数时,您需要释放写锁定sem_post(&write);稍后再做更多。

out函数中,您将采用反之亦然的方法,您将等待写锁定被释放sem_wait(&write);最后您将释放读锁定sem_post(&read);

现在,在main中,您需要初始化两个信号量:

sem_init(&read, 0, 1);
sem_init(&write, 0, 0);

请注意,我用值 1 初始化了read,用值 0 初始化了write。原因是sem_wait将检查信号量的值,如果大于 0,它将递减该值并继续处理。由于我们希望函数calc函数out函数之前运行,因此我们用 1 初始化read变量,这样它就不会等待第一次命中并继续处理。

而在out函数中,我们需要先赋值,然后才能打印/处理它们。因此write变量初始化为 0,它将等到函数完成并通过调用sem_post(&write);calc函数将write从 0 增加到 1

您可以使用要创建的线程数初始化read变量,但在这种情况下,将发生争用情况,并且在函数处理数据之前可能会out数据被覆盖。为了克服这种情况,您需要为列表或数组等值创建一个缓冲区。还有一个额外的信号量来控制互斥锁,它将在每次sem_wait()之后和每次sem_post()之前调用,以便不会同时访问值缓冲区。

有关信号量的详细示例可在此处找到:

建议:

使用一两个互斥锁

  1. 生成一个pthread_mutex_t mutexName;,每个线程使用该以避免在更新/访问计数器和其他关键数据时出现争用条件
  2. "显示"线程通过调用pthread_cond_t condName;阻塞:pthread_cond_wait( condName );
  3. 每次线程更新计数器时,它都会调用pthread_cond_signal( condName ),导致"display"线程继续处理。 当"显示"线程完成处理时,它会再次阻塞"pthread_cond">
  4. 强烈建议阅读: pthread_cond

注意:由于各种计时考虑,正在访问的数据应该是循环队列,因此不会"丢失"数据更新

最新更新