为什么 printf 不能在 c 中使用多线程?
Why printf is not working with multple threads in c?
在下面的代码中,我创建了 8 个线程,每个线程都打印一个字符串及其 ID。但是,我没有在 PrintHello
函数的 stdout
中看到任何 printf
输出。正在发生的一件奇怪的事情是,如果 运行 使用调试器 (CLion) printf
的 main
确实输出了预期的输出。我实际上怀疑 PrintHello
函数中没有代码是 运行,而不仅仅是 printf
。可能是什么原因造成的?
此外,answer printf
是线程安全的,因此不应该是不同线程竞争 stdout
.
的问题
这是代码(改编自这些slides):
#include <stdio.h>
#include <stdlib.h>
#include <ntsid.h>
#include <pthread.h>
#include <unistd.h>
#define BAD_EXIT 1
#define NUM_TASKS 8
char * messages[NUM_TASKS];
void * PrintHello(void * taskIdPtr) {
int taskId;
sleep(1);
taskId = *((int *) taskIdPtr);
printf("Task id = %d, message = %s\n", taskId, messages[taskId]);
free(taskIdPtr);
pthread_exit(NULL);
}
int main(int argc, char ** argv) {
pthread_t threads[NUM_TASKS];
int * taskIdPtr;
int rc, t;
messages[0] = "English: Hello World!";
messages[1] = "French: Bonjour, le monde!";
messages[2] = "Spanish: Hola al mundo";
messages[3] = "Klingon: Nuq neH!";
messages[4] = "German: Guten Tag, Welt!";
messages[5] = "Russian: Zdravstvytye, mir!";
messages[6] = "Japan: Sekai e konnichiwa!";
messages[7] = "Latin: Orbis, te saluto!";
for(t = 0; t < NUM_TASKS; t++) {
taskIdPtr = (int *) malloc(sizeof(int));
*taskIdPtr = t;
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskIdPtr);
if(rc) {
perror("Error :");
exit(BAD_EXIT);
}
}
return 0;
}
在执行新创建的线程之前,主进程正在退出。所以你应该等待使用 pthread_join
.
创建的线程
根据 pthread_join
的手册页
int pthread_join(pthread_t thread, void **retval);
pthread_join()函数等待thread指定的线程终止。如果该线程已经终止,则立即 pthread_join() returns。 thread 指定的线程必须是可连接的。
问题是您的 主线程 在任何其他子线程甚至打印一条消息之前完成执行并退出(因为在您的子线程中您正在等待 1 秒之前做任何事)。
一旦 主线程 退出,所有其他子线程也会退出,您在屏幕上看不到任何消息。
以下是 pthread_create()
的 linux 手册页的摘录:
The new thread terminates in one of the following ways:
- It calls pthread_exit(3), specifying an exit status value that is available to another thread in the same process that calls pthread_join(3).
- It returns from start_routine(). This is equivalent to calling pthread_exit(3) with the value supplied in the return statement.
- It is canceled (see pthread_cancel(3)).
- Any of the threads in the process calls exit(3), or the main thread performs a return from main(). This causes the termination of all threads in the process.
要解决此问题,您应该使用 int pthread_join(pthread_t thread, void **retval)
。
以下是更正后的代码。看看吧working here:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define BAD_EXIT 1
#define NUM_TASKS 8
char * messages[NUM_TASKS];
void * PrintHello(void * taskIdPtr) {
int taskId;
sleep(1);
taskId = *((int *) taskIdPtr);
printf("Task id = %d, message = %s\n", taskId, messages[taskId]);
free(taskIdPtr);
pthread_exit(NULL);
}
int main(int argc, char ** argv) {
pthread_t threads[NUM_TASKS];
int * taskIdPtr;
int rc, t;
messages[0] = "English: Hello World!";
messages[1] = "French: Bonjour, le monde!";
messages[2] = "Spanish: Hola al mundo";
messages[3] = "Klingon: Nuq neH!";
messages[4] = "German: Guten Tag, Welt!";
messages[5] = "Russian: Zdravstvytye, mir!";
messages[6] = "Japan: Sekai e konnichiwa!";
messages[7] = "Latin: Orbis, te saluto!";
for(t = 0; t < NUM_TASKS; t++) {
taskIdPtr = (int *) malloc(sizeof(int));
*taskIdPtr = t;
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskIdPtr);
if(rc) {
perror("Error :");
exit(BAD_EXIT);
}
}
for(t = 0; t < NUM_TASKS; t++)
{
pthread_join(threads[t], NULL);
}
return 0;
}
在下面的代码中,我创建了 8 个线程,每个线程都打印一个字符串及其 ID。但是,我没有在 PrintHello
函数的 stdout
中看到任何 printf
输出。正在发生的一件奇怪的事情是,如果 运行 使用调试器 (CLion) printf
的 main
确实输出了预期的输出。我实际上怀疑 PrintHello
函数中没有代码是 运行,而不仅仅是 printf
。可能是什么原因造成的?
此外,answer printf
是线程安全的,因此不应该是不同线程竞争 stdout
.
这是代码(改编自这些slides):
#include <stdio.h>
#include <stdlib.h>
#include <ntsid.h>
#include <pthread.h>
#include <unistd.h>
#define BAD_EXIT 1
#define NUM_TASKS 8
char * messages[NUM_TASKS];
void * PrintHello(void * taskIdPtr) {
int taskId;
sleep(1);
taskId = *((int *) taskIdPtr);
printf("Task id = %d, message = %s\n", taskId, messages[taskId]);
free(taskIdPtr);
pthread_exit(NULL);
}
int main(int argc, char ** argv) {
pthread_t threads[NUM_TASKS];
int * taskIdPtr;
int rc, t;
messages[0] = "English: Hello World!";
messages[1] = "French: Bonjour, le monde!";
messages[2] = "Spanish: Hola al mundo";
messages[3] = "Klingon: Nuq neH!";
messages[4] = "German: Guten Tag, Welt!";
messages[5] = "Russian: Zdravstvytye, mir!";
messages[6] = "Japan: Sekai e konnichiwa!";
messages[7] = "Latin: Orbis, te saluto!";
for(t = 0; t < NUM_TASKS; t++) {
taskIdPtr = (int *) malloc(sizeof(int));
*taskIdPtr = t;
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskIdPtr);
if(rc) {
perror("Error :");
exit(BAD_EXIT);
}
}
return 0;
}
在执行新创建的线程之前,主进程正在退出。所以你应该等待使用 pthread_join
.
根据 pthread_join
int pthread_join(pthread_t thread, void **retval);
pthread_join()函数等待thread指定的线程终止。如果该线程已经终止,则立即 pthread_join() returns。 thread 指定的线程必须是可连接的。
问题是您的 主线程 在任何其他子线程甚至打印一条消息之前完成执行并退出(因为在您的子线程中您正在等待 1 秒之前做任何事)。
一旦 主线程 退出,所有其他子线程也会退出,您在屏幕上看不到任何消息。
以下是 pthread_create()
的 linux 手册页的摘录:
The new thread terminates in one of the following ways:
- It calls pthread_exit(3), specifying an exit status value that is available to another thread in the same process that calls pthread_join(3).
- It returns from start_routine(). This is equivalent to calling pthread_exit(3) with the value supplied in the return statement.
- It is canceled (see pthread_cancel(3)).
- Any of the threads in the process calls exit(3), or the main thread performs a return from main(). This causes the termination of all threads in the process.
要解决此问题,您应该使用 int pthread_join(pthread_t thread, void **retval)
。
以下是更正后的代码。看看吧working here:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define BAD_EXIT 1
#define NUM_TASKS 8
char * messages[NUM_TASKS];
void * PrintHello(void * taskIdPtr) {
int taskId;
sleep(1);
taskId = *((int *) taskIdPtr);
printf("Task id = %d, message = %s\n", taskId, messages[taskId]);
free(taskIdPtr);
pthread_exit(NULL);
}
int main(int argc, char ** argv) {
pthread_t threads[NUM_TASKS];
int * taskIdPtr;
int rc, t;
messages[0] = "English: Hello World!";
messages[1] = "French: Bonjour, le monde!";
messages[2] = "Spanish: Hola al mundo";
messages[3] = "Klingon: Nuq neH!";
messages[4] = "German: Guten Tag, Welt!";
messages[5] = "Russian: Zdravstvytye, mir!";
messages[6] = "Japan: Sekai e konnichiwa!";
messages[7] = "Latin: Orbis, te saluto!";
for(t = 0; t < NUM_TASKS; t++) {
taskIdPtr = (int *) malloc(sizeof(int));
*taskIdPtr = t;
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskIdPtr);
if(rc) {
perror("Error :");
exit(BAD_EXIT);
}
}
for(t = 0; t < NUM_TASKS; t++)
{
pthread_join(threads[t], NULL);
}
return 0;
}