如何在多个线程中使用printf()

我正在实现一个使用不同内核的multithreading程序,并且许multithreading被同时执行。 每个线程都进行printf()调用,结果是不可读的。

我怎样才能使printf()primefaces,以便一个线程中的printf()调用不会与另一个线程中的printf()调用冲突?

Solutions Collecting From Web of "如何在多个线程中使用printf()"

为了不混合来自不同线程的输出,您需要确保一次只有一个线程使用printf 。 要做到这一点,最简单的解决方案就是使用mutex 。 在开始初始化mutex

 static pthread_mutex_t printf_mutex; ... int main() { ... pthread_mutex_init(&printf_mutex, NULL); ... 

然后围绕printf做一个包装,确保只有获得mutex才能调用printf (否则将不得不阻塞,直到mutex量可用):

 int sync_printf(const char *format, ...) { va_list args; va_start(args, format); pthread_mutex_lock(&printf_mutex); vprintf(format, args); pthread_mutex_unlock(&printf_mutex); va_end(args); } 

POSIX规范

POSIX规范包含这些功能:

  • getc_unlocked()
  • getchar_unlocked()
  • putc_unlocked()
  • putchar_unlock()

提供了函数getc()getchar()putc()putchar()分别命名为getc_unlocked()getchar_unlocked()putc_unlocked()putchar_unlocked()只是它们不需要以完全线程安全的方式来实现。 在flockfile() (或ftrylockfile() )和funlockfile()保护的作用flockfile()使用时,它们应该是线程安全的。 这些函数可以安全地在多线程程序中使用,当且仅当在调用线程拥有( FILE * )对象的情况下调用这些函数,就像成功调用flockfile()ftrylockfile()函数后的情况一样。

这些功能的规范提到:

  • flockfile()
  • ftrylockfile()
  • funlockfile()

flockfile()等规范包含了一揽子要求:

所有引用( FILE * )对象的函数,除名称以_unlocked结尾的函数外,其行为就像在内部使用flockfile()funlockfile()来获得这些( FILE * )对象的所有权一样。

这取代了此答案以前版本中的建议代码。 POSIX标准还规定:

[ *lockfile() ]函数的行为就好像每个( FILE * )对象都有一个锁计数。 ( FILE * )对象创建时,此计数隐式初始化为零。 计数为零时( FILE * )对象被解锁。 当count是正数时,单个线程拥有( FILE * )对象。 调用flockfile()函数时,如果计数为零,或者如果计数为正数且调用方拥有( FILE * )对象,则计数应递增。 否则,调用线程将被挂起,等待计数返回到零。 每次调用funlockfile()减少计数。 这允许匹配调用flockfile() (或成功调用ftrylockfile() )和funlockfile()来嵌套。

还有字符I / O功能的规格:

  • getc()
  • getchar()
  • putc()
  • putchar()
  • fgetc()
  • fputc()

格式化的输出功能记录在这里:

  • printf()

printf()规范中的一个关键规定是:

fprintf()printf()生成的字符被打印,就像fputc()被调用一样。

请注意“如果”的使用 。 但是,每个printf()函数都需要应用该锁,以便在多线程应用程序中控制对流的访问。 一次只有一个线程可以使用给定的文件流。 如果操作是对fputc()用户级调用,则其他线程可以散布输出。 如果操作是用户级调用(如printf() ,则整个调用和对文件流的所有访问都将得到有效保护,以便只有一个线程正在使用它,直到printf()调用返回。

在关于线程主题的POSIX的系统接口:一般信息部分,它说:

2.9.1线程安全

本卷所定义的所有函数都应该是线程安全的,除了以下函数1不必是线程安全的。

一个不需要线程安全的函数列表

除非调用线程拥有由调用访问的( FILE * )对象,否则getc_unlocked()getchar_unlocked()putc_unlocked()putchar_unlocked()函数不必是线程安全的,调用成功flockfile()ftrylockfile()函数。

为了满足这个要求,实现必须提供内部同步。

豁免函数列表不包含fputcputcputchar (或printf()等)。

解释

重写2017-07-26。

  1. 流中的字符级输出是线程安全的,除非在不先锁定文件的情况下使用“解锁”函数。
  2. 比如printf()这样的更高级的函数在结束时从概念上调用flockfile() ,这意味着POSIX定义的流输出函数在每次调用时也是线程安全的。
  3. 如果您希望在单个线程的文件流上对操作进行分组,则可以通过在相关流上明确使用对flockfile()funlockfile()调用来flockfile() ,而不会干扰系统使用*lockfile()函数。

这意味着不需要为自己创建互斥或等效机制。 该实现提供的功能允许您控制对多线程应用程序中printf()等的访问。

…代码从以前的答案删除不再相关…

对于linux,这里是c:3线程中的u代码,在不同的核心上执行,打印hello world,而不是与其他锁相冲突。

 #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <syscall.h> #include <sys/types.h> void * printA ( void *); void * printB ( void *); void * printC ( void *); pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; int main(int argc, char *argv[]) { int error; pthread_t tid1, tid2,tid3; if ( error = pthread_create (&tid1, NULL, printA, NULL )) { fprintf (stderr, "Failed to create first thread: %s\n",strerror(error)); return 1; } if ( error = pthread_create (&tid2, NULL, printB, NULL )) { fprintf (stderr, "Failed to create second thread: %s\n",strerror(error)); return 1; } if ( error = pthread_create (&tid3, NULL, printC, NULL )) { fprintf (stderr, "Failed to create second thread: %s\n",strerror(error)); return 1; } if (error = pthread_join(tid1, NULL)) { fprintf (stderr, "Failed to join first thread: %s\n",strerror(error)); return 1; } if (error = pthread_join(tid2, NULL)) { fprintf (stderr, "Failed to join second thread: %s\n",strerror(error)); return 1; } if (error = pthread_join(tid3, NULL)) { fprintf (stderr, "Failed to join second thread: %s\n",strerror(error)); return 1; } return 0; } void * printA ( void *arg ) { if ( error = pthread_mutex_lock( &mylock )) { fprintf (stderr, "Failed to acquire lock in printA: %s\n",strerror(error)); return NULL; } printf("Hello world\n"); if ( error = pthread_mutex_unlock( &mylock )) { fprintf (stderr, "Failed to release lock in printA: %s\n",strerror(error)); return NULL; } } void * printB ( void *arg ) { int error; if ( error = pthread_mutex_lock( &mylock )) { fprintf (stderr, "Failed to acquire lock in printB: %s\n",strerror(error)); return NULL; } printf("Hello world\n"); if ( error = pthread_mutex_unlock( &mylock )) { fprintf (stderr, "Failed to release lock in printA: %s\n",strerror(error)); return NULL; } } void * printC ( void *arg ) { int error; if ( error = pthread_mutex_lock( &mylock )) { fprintf (stderr, "Failed to acquire lock in printB: %s\n",strerror(error)); return NULL; } printf("Hello world\n"); if ( error = pthread_mutex_unlock( &mylock )) { fprintf (stderr, "Failed to release lock in printA: %s\n",strerror(error)); return NULL; } }