首页 > 解决方案 > 多线程测试 C 应用程序挂起,除非使用 printf

问题描述

我正在尝试学习 C 中多线程的来龙去脉。我从这个小例子开始:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> //Header file for sleep(). man 3 sleep for details. 
#include <pthread.h> 

#define TOTAL_TS  1000
#define WAIT_TS   74

int timeStepCounter;

// A normal C function that is executed as a thread 
// when its name is specified in pthread_create() 
void *longProcess(void *vargp) 
{ 
   int endtime = timeStepCounter + WAIT_TS;
    while (timeStepCounter < endtime);
    printf("Finished when timeStepCounter is %d\n",timeStepCounter); 
    return NULL; 
} 

int main() 
{ 

   pthread_t thread_id; 

   for (timeStepCounter = 0; timeStepCounter < TOTAL_TS; timeStepCounter++){
      if (timeStepCounter == 158){         
         printf("Creating thread @ %d\n",timeStepCounter);
         pthread_create(&thread_id, NULL, longProcess, NULL); 
      }    
      //printf("TimeStep is: %d\n",timeStepCounter);
   }

   pthread_join(thread_id, NULL); 
   printf("Finished\n"); 

   return 0;

}

我已经从互联网示例中对其进行了修改。

这就是发生的事情。当您按原样运行它时,程序在打印“正在创建线程...”消息后挂起。

但是,如果我取消注释打印 TimeStep 的 printf,应用程序将按预期工作。

所以我的问题是为什么?

编辑:正如@Bodo 所建议的那样,我将一个指向互联网示例的链接作为我的代码的基础:https ://www.geeksforgeeks.org/multithreading-c-2/

标签: cmultithreading

解决方案


正如groo的评论中提到的,如果新创建的线程在主线程已经完成循环时开始执行,则程序无法正常工作。

当主线程没有被调用延迟时,这可能会发生printf

添加一行

printf("Thread started when timeStepCounter is %d\n",timeStepCounter);

while (timeStepCounter < endtime);

你可能会看到

Thread started when timeStepCounter is 1000

此外,您必须将多个线程访问的变量声明为volatile,即

volatile int timeStepCounter;

并确保它使用具有原子访问的类型。(如果它不是原子的,则需要同步。)

即使只有一个线程修改了值,经过优化的编译器也会发现timeStepCounter在循环中没有修改

while (timeStepCounter < endtime);

并产生类似的代码

while(1);

该关键字volatile通知编译器该值可能会在程序的正常流程之外被修改,当您使用线程时会发生什么。(编译器不知道线程。)

volatile我可以通过在没有和没有注释printf的情况下编译代码来验证这一点

gcc -g -Wall -Wextra -pedantic -O3    test.c  -lpthread -o test

我得到例如

...
Creating thread @ 158
...
Thread started when timeStepCounter is 226
...

但不是

Finished when timeStepCounter is ...

推荐阅读