3

我有以下代码:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define LOOPS 10000

void *run(void *arg)
{
    int id = strtol(arg,NULL,0);
    int i;
    for(i=0; i<LOOPS; i++)
    {
        printf("In %d.\n",id);
    }
}

int main()
{
    pthread_t p1,p2;
    void *res;

    pthread_create(&p1,NULL,run,"1");
    pthread_create(&p2,NULL,run,"2");
    pthread_join(p1,&res);
    pthread_join(p2,&res);
    return 0;
}

当我运行它时,字符串“In 1”连续显示 10000 次,然后“In 2”连续显示 10000 次,反之亦然。字符串不应该像这里一样交替显示而不是连续显示吗?

4

3 回答 3

8

调度程序交错线程的顺序不是确定性的(……嗯,但仅从调度程序/内核的角度来看)。您不应该对订单做出假设。

这种情况下,您会体验到任何一个线程都可以在调度程序->抢占它并​​允许另一个线程运行之前完成它们的全部工作。

于 2013-02-17T17:51:36.070 回答
2

调度程序在时隙中运行进程。时隙足够大以提高效率,但又足够小以产生同时执行的错觉。

在多核 CPU 上,在操作系统内核级别实现的线程实际上将并行执行。

最重要的是,输出有时会被缓冲,因为进行一次大写所需的处理能力与进行一次小写所需的处理能力大致相同。当输出到交互式终端设备时,大多数系统都禁用缓冲,但现在环境的细节开始变得非常重要。

对于要交错的输出,它必须是无缓冲的并在多核或异常细粒度的调度程序上运行,并且愿意仅仅因为您产生一行输出而进行昂贵的上下文切换。如果是多核,则通过库和内核的执行路径必须同时在三个核上平衡。这可能永远不会发生。

毕竟,您一次创建一个,而一个总是准备好在另一个之前运行。

于 2013-02-17T18:04:53.857 回答
2

其他两个答案是正确的,但我想补充一点:

两个输出交错的。它们只是不是每隔一两行交错一次,而是更可能是数千行。当每个线程被赋予一个时间量时,它就有输出数千行的时间。由于您只在每个线程上打印 10k 行,因此一个线程有时间在另一个线程开始之前完成它的工作。

尝试用for无限循环替换你的循环,看看会发生什么。

于 2013-02-17T18:08:25.453 回答