c - 多线程测试 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/
解决方案
正如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 ...
推荐阅读
- eclipse - 理解使用约束违规
- linux - 为什么Golang实现的程序不使用libc.so.6的函数,比如socket()?
- c++ - If 语句问题 [C++]
- android - Android FloatingActionButton 波纹无法正常工作
- javascript - 从数组内部更新对象属性
- python - 有什么方法可以正确聚合时间序列数据以使用 matplotlib/seaborn 制作散点图?
- vba - 从 2 个组合框更新字段(风险矩阵)
- javascript - 使用 jQuery 访问动态名称变量
- python - 使用漂亮的汤在一个类中获取多个标签
- azure-active-directory - 使用 azure ad 对应用服务进行身份验证(图表)