多线程printf vs write(2)缓冲

时间:2016-09-10 15:53:04

标签: solaris c io printf multithreading

考虑在Solaris 11.3下运行的以下代码:

void *run(void *args) {
  int i;
  for (i = 0; i < 100; i++) {
    printf("Line #%d printed by child\n", i + 1);
  }
}

int main() {
  pthread_t tid;
  int ret = pthread_create(&tid, NULL, run, NULL);
  int i;
  for (i = 0; i < 100; i++) {
    printf("Line #%d printed by parent\n", i + 1);
  }
  pthread_exit(NULL);
}

运行后,父线程始终在新创建的线程之前打印出所有行。有些人可能会说pthread_create太慢,以至于在主线程返回之前,其他线程甚至无法启动其工作。但是,为printf换出write(2)会产生 线程偶尔轮流印刷线的预期输出。

如何解释这种行为?

缓冲肯定与它无关,因为默认情况下终端输出是行缓冲的; writeprintf都应该如此。

即使函数使用某种阻塞技术来提供线程安全性,究竟是什么阻止了输出的加扰?

1 个答案:

答案 0 :(得分:1)

由于速度,这是很好的。如果您在usleep和循环之间调用pthread_create,并稍微调整一下该值,则可以将其混合使用。

请注意,由于stdio锁定,一旦一个线程无法在stdout上获取一次或两次锁定,它可能会睡眠几毫秒(这将允许另一个线程完成其循环),所以你不会看到很多混音。如果你想要更多混音,你也需要在循环中加上usleep

在我的机器上,在父项循环之前usleep(50),两个循环中的usleep(1)将导致几乎交替的行。