为什么 printf 不能在 c 中使用多线程?

Why printf is not working with multple threads in c?

在下面的代码中,我创建了 8 个线程,每个线程都打印一个字符串及其 ID。但是,我没有在 PrintHello 函数的 stdout 中看到任何 printf 输出。正在发生的一件奇怪的事情是,如果 运行 使用调试器 (CLion) printfmain 确实输出了预期的输出。我实际上怀疑 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;
}