为什么这两个线程不同步运行?
Why does these two threads not run synchronously?
我有以下程序生成两个线程到 print_something()
,它们都重复打印特定字符串:线程 1 打印 "Hi\n"
,线程 2 打印 "Bye\n"
:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *print_something(int *k)
{
int n = 100;
int i;
if (*k) {
for (i = 0; i < 100; i++) {
printf("Hi\n");
}
} else {
for (i = 0; i < 100; i++) {
printf("Bye\n");
}
}
}
int main()
{
int x = 1, y = 0;
pthread_t t1, t2;
pthread_create(&t1, NULL, print_something, &x);
pthread_create(&t2, NULL, print_something, &y);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("End of program.\n");
return 0;
}
我希望它们同步 运行,其中终端中的输出是随机的,例如:
Hi
Hi
Bye
Hi
Bye
...
但是我总是让线程 1 在线程 2 开始打印之前先完成打印:
Hi
Hi
...
Hi
Hi
Bye
Bye
...
Bye
Bye
End of program.
为什么第一个线程阻止第二个线程打印?
Why is the first thread blocking the second thread from printing?
谁说阻塞了?也许启动一个新线程需要足够长的时间,以至于第一个附加线程(运行 与原始线程并行)在第二个附加线程到达尝试打印任何内容之前完成其打印(到 stdout 的缓冲区)。
另一方面,POSIX 确实指定 stdio 函数对流执行操作,就好像每个流都有一个锁相关联,线程必须在进入函数时获得锁并在退出时释放锁。因此,第一个线程可能确实通过与 stdout
.
关联的锁阻塞了第二个线程
此外,当一个线程解锁一个锁然后立即尝试重新获取同一个锁时,尽管其他线程争用该锁,该线程很可能立即成功。因此,当整个循环体以获取锁开始并以释放该锁结束时——就像你的代码中关联锁 stdout
的情况一样——一个线程通常能够独占多次循环迭代的锁。
I expected them to run synchronously wherein the output in the terminal would be random such as:
这是一个不合理的期望。如果两个人每人需要拧一百个螺丝并且共用一把螺丝刀,你认为他们应该在每个螺丝完成后交出螺丝刀吗?只有拿螺丝刀的人累了才把螺丝刀递过去。
每个线程将绝大部分时间花在访问控制台输出流上。它只能通过排除其他线程来做到这一点。您期望的行为将是残酷的。
它们会 运行 在同一个核心上吗?这将需要在每一行输出之后进行上下文切换——此代码可能的最差性能。他们会 运行 在两个核心上吗?这意味着每个核心都在等待另一个核心完成控制台的时间大约有一半——性能也很糟糕。
简而言之,您希望您的系统找到一种糟糕的方式来完成您要求它做的事情。它找到了一种更更有效的方法——让一个线程保留控制台,完成它正在做的事情,然后让另一个线程离开。
我有以下程序生成两个线程到 print_something()
,它们都重复打印特定字符串:线程 1 打印 "Hi\n"
,线程 2 打印 "Bye\n"
:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *print_something(int *k)
{
int n = 100;
int i;
if (*k) {
for (i = 0; i < 100; i++) {
printf("Hi\n");
}
} else {
for (i = 0; i < 100; i++) {
printf("Bye\n");
}
}
}
int main()
{
int x = 1, y = 0;
pthread_t t1, t2;
pthread_create(&t1, NULL, print_something, &x);
pthread_create(&t2, NULL, print_something, &y);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("End of program.\n");
return 0;
}
我希望它们同步 运行,其中终端中的输出是随机的,例如:
Hi
Hi
Bye
Hi
Bye
...
但是我总是让线程 1 在线程 2 开始打印之前先完成打印:
Hi
Hi
...
Hi
Hi
Bye
Bye
...
Bye
Bye
End of program.
为什么第一个线程阻止第二个线程打印?
Why is the first thread blocking the second thread from printing?
谁说阻塞了?也许启动一个新线程需要足够长的时间,以至于第一个附加线程(运行 与原始线程并行)在第二个附加线程到达尝试打印任何内容之前完成其打印(到 stdout 的缓冲区)。
另一方面,POSIX 确实指定 stdio 函数对流执行操作,就好像每个流都有一个锁相关联,线程必须在进入函数时获得锁并在退出时释放锁。因此,第一个线程可能确实通过与 stdout
.
此外,当一个线程解锁一个锁然后立即尝试重新获取同一个锁时,尽管其他线程争用该锁,该线程很可能立即成功。因此,当整个循环体以获取锁开始并以释放该锁结束时——就像你的代码中关联锁 stdout
的情况一样——一个线程通常能够独占多次循环迭代的锁。
I expected them to run synchronously wherein the output in the terminal would be random such as:
这是一个不合理的期望。如果两个人每人需要拧一百个螺丝并且共用一把螺丝刀,你认为他们应该在每个螺丝完成后交出螺丝刀吗?只有拿螺丝刀的人累了才把螺丝刀递过去。
每个线程将绝大部分时间花在访问控制台输出流上。它只能通过排除其他线程来做到这一点。您期望的行为将是残酷的。
它们会 运行 在同一个核心上吗?这将需要在每一行输出之后进行上下文切换——此代码可能的最差性能。他们会 运行 在两个核心上吗?这意味着每个核心都在等待另一个核心完成控制台的时间大约有一半——性能也很糟糕。
简而言之,您希望您的系统找到一种糟糕的方式来完成您要求它做的事情。它找到了一种更更有效的方法——让一个线程保留控制台,完成它正在做的事情,然后让另一个线程离开。