我对这个例子感到困惑:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void *thread_func()
{
sleep(1); // removing this changes the result
printf("n");
return NULL;
}
int main()
{
int i;
for (i = 0; i < 10000; i++)
{
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
}
pthread_exit(NULL);
return 0;
}
如果我用sleep(1)
运行这个,我会计算2047行,没有10000行,正如预期的那样。这是怎么回事?
编辑:将预期行数更正为10000。
由于程序在退出之前不会等待线程,因此在退出程序销毁所有线程之前,它有一个模糊定义的运行时间。
更新:pthread_exit
确实在等待线程。对于正在运行的线程。我怀疑发生的情况是,pthread_create
创建的线程在pthread_exit
之前没有完全构建,然后程序退出。线程构造的一部分发生在新线程中,所以如果它从未被调度运行,那么该线程也可能不存在。
创建10000个线程需要时间。摧毁它们也是如此。与此同时,显然有3000个线程设法到达printf语句。
打印的时间和数量取决于许多不同的因素,因此也可能是随机的。
抛开所示代码试图创建10000个线程不谈,如果成功创建,将打印10000行而不是3000行,核心问题是:
如果每个线程等待1秒,为什么print
的线程比不等待的线程少?
可能的原因:
每个线程都会消耗资源。因此,并发存在的线程的最大数量是有限的。
如果每个线程在结束前等待1s,则可以假设可用资源消耗得比线程立即退出更快。因此,如果资源耗尽,线程的创建就会失败,代码会忽略这一点,而只是尝试创建下一个线程。
要查看真正发生了什么,代码应该记录创建失败的情况,如下所示:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
void *thread_func(void)
{
sleep(1); /* Removing this probably lowers the number of failed creations. */
printf("n");
return NULL;
}
int main(void)
{
int i;
for (i = 0; i < 10000; i++)
{
pthread_t tid;
if (errno = pthread_create(&tid, NULL, thread_func, NULL))
{
perror("pthread_create() failed");
}
}
pthread_exit(NULL);
/* Never arriving here. */
return 0;
}
上述代码打印的行数预计总共为10000行,其中一些行为空,将转到stdout
,一些列示创建失败,将转到stderr
。