Pthread 冻结标准输出?
Pthread freezes stdout?
假设 C++ 程序中有两个线程 (pthread):
-
main thread
child thread
程序的作用很简单:
- 将两个线程绑定到两个不同的内核。
- 将两个线程的优先级设置为一些非常高的值(
child thread
为 -99,main thread
为 -98)。
child thread
正在执行一些使用 100% CPU 的繁重任务。
main thread
在创建 child thread
后尝试调用 printf()。
问题是,一旦子线程被创建,它就会冻结标准输出并且控制台上不再打印任何内容。但是,当程序退出时,所有消息突然显示在控制台中。下面是演示此效果的 .cpp 文件:
main.cpp:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mman.h>
bool EXIT = false;
void signal_handler(int signal){
EXIT = true;
}
void *child_thread(void *x_args){
printf("Setting child thread CPU affinity (Core #1)...\n");
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(1, &cpuset);
if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)){
perror("Cannot set child thread CPU affinity");
printf("Exit\n");
exit(1);
}
printf("Locking memory of child thread...\n");
mlockall(MCL_CURRENT | MCL_FUTURE);
printf("Setting child thread priority (-99)...\n");
struct sched_param sched_param;
sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
if (sched_setscheduler(0, SCHED_FIFO, &sched_param)){
perror("Cannot set child thread priority");
printf("Exit\n");
exit(1);
}
printf("Entering while loop inside child thread...\n");
while(!EXIT){}
return NULL;
}
int main(){
signal(SIGINT, signal_handler);
pthread_t thread;
printf("Setting main thread CPU affinity (Core #0)...\n");
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(0, &cpuset);
if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)){
perror("Cannot set main thread CPU affinity");
printf("Exit.\n");
exit(1);
}
printf("Locking memory of main thread...\n");
mlockall(MCL_CURRENT | MCL_FUTURE);
printf("Setting main thread priority (-98)...\n");
struct sched_param sched_param;
sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-2;
if (sched_setscheduler(0, SCHED_FIFO, &sched_param)){
perror("Cannot set main thread priority");
printf("Exit.\n");
exit(1);
}
printf("Creating child thread...\n");
if (pthread_create(&thread, NULL, child_thread, NULL)){
perror("Cannot create child thread");
printf("Exit.\n");
exit(1);
}
printf("Entering while loop in main thread...\n");
while(!EXIT){
sleep(1);
printf("I can't see this until I press Ctrl+C!\n");
}
pthread_join(thread, NULL);
printf("Exit.\n");
return 0;
}
你可以编译它:
g++ main.cpp -pthread -o main
然后 运行 它与:
sudo ./main
然后你应该看到 stdout 在输出以下内容后冻结:
Setting main thread CPU affinity (Core #0)...
Locking memory of main thread...
Setting main thread priority (-98)...
Creating child thread...
Entering while loop in main thread...
Setting child thread CPU affinity (Core #1)...
即使在一个小时后,您也看不到任何输出。但是当 Ctrl+C
被按下时。你会看到所有的消息都出来了:
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
main thread
实际上是在后台 运行ning 因为如果你注释掉 while 循环中的两行(sleep 和 printf),你可以看到它也在使用 100 CPU 的百分比。但是ht
我在这里错过了什么?
我不会声称自己是专家,但您似乎只有一个资源、stdout 和两个试图使用它的线程。我相信 printf 是线程安全的,但不是可重入的。
我的直觉是在对 printf 和 stdout 的访问周围使用某种线程安全锁定,以确保一次只有一个线程调用它。
假设 C++ 程序中有两个线程 (pthread):
-
main thread
child thread
程序的作用很简单:
- 将两个线程绑定到两个不同的内核。
- 将两个线程的优先级设置为一些非常高的值(
child thread
为 -99,main thread
为 -98)。 child thread
正在执行一些使用 100% CPU 的繁重任务。main thread
在创建child thread
后尝试调用 printf()。
问题是,一旦子线程被创建,它就会冻结标准输出并且控制台上不再打印任何内容。但是,当程序退出时,所有消息突然显示在控制台中。下面是演示此效果的 .cpp 文件:
main.cpp:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mman.h>
bool EXIT = false;
void signal_handler(int signal){
EXIT = true;
}
void *child_thread(void *x_args){
printf("Setting child thread CPU affinity (Core #1)...\n");
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(1, &cpuset);
if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)){
perror("Cannot set child thread CPU affinity");
printf("Exit\n");
exit(1);
}
printf("Locking memory of child thread...\n");
mlockall(MCL_CURRENT | MCL_FUTURE);
printf("Setting child thread priority (-99)...\n");
struct sched_param sched_param;
sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
if (sched_setscheduler(0, SCHED_FIFO, &sched_param)){
perror("Cannot set child thread priority");
printf("Exit\n");
exit(1);
}
printf("Entering while loop inside child thread...\n");
while(!EXIT){}
return NULL;
}
int main(){
signal(SIGINT, signal_handler);
pthread_t thread;
printf("Setting main thread CPU affinity (Core #0)...\n");
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(0, &cpuset);
if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)){
perror("Cannot set main thread CPU affinity");
printf("Exit.\n");
exit(1);
}
printf("Locking memory of main thread...\n");
mlockall(MCL_CURRENT | MCL_FUTURE);
printf("Setting main thread priority (-98)...\n");
struct sched_param sched_param;
sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-2;
if (sched_setscheduler(0, SCHED_FIFO, &sched_param)){
perror("Cannot set main thread priority");
printf("Exit.\n");
exit(1);
}
printf("Creating child thread...\n");
if (pthread_create(&thread, NULL, child_thread, NULL)){
perror("Cannot create child thread");
printf("Exit.\n");
exit(1);
}
printf("Entering while loop in main thread...\n");
while(!EXIT){
sleep(1);
printf("I can't see this until I press Ctrl+C!\n");
}
pthread_join(thread, NULL);
printf("Exit.\n");
return 0;
}
你可以编译它:
g++ main.cpp -pthread -o main
然后 运行 它与:
sudo ./main
然后你应该看到 stdout 在输出以下内容后冻结:
Setting main thread CPU affinity (Core #0)...
Locking memory of main thread...
Setting main thread priority (-98)...
Creating child thread...
Entering while loop in main thread...
Setting child thread CPU affinity (Core #1)...
即使在一个小时后,您也看不到任何输出。但是当 Ctrl+C
被按下时。你会看到所有的消息都出来了:
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
I can't see this until I press Ctrl+C!
main thread
实际上是在后台 运行ning 因为如果你注释掉 while 循环中的两行(sleep 和 printf),你可以看到它也在使用 100 CPU 的百分比。但是ht
我在这里错过了什么?
我不会声称自己是专家,但您似乎只有一个资源、stdout 和两个试图使用它的线程。我相信 printf 是线程安全的,但不是可重入的。 我的直觉是在对 printf 和 stdout 的访问周围使用某种线程安全锁定,以确保一次只有一个线程调用它。