万事如意!我在各种资料中读到 printf() 函数是线程安全的,并且可以由不同的线程调用,以便将无冲突的输出输出到控制台(当然,前提是参数传递正确)。事实上,这个函数总是处理多线程输出,我实际使用了它......直到我需要编译支持 C ++ 17 标准的程序!一般来说,这里有一个最小可重复的例子来说明问题的本质:
#include <stdio.h>
#include <conio.h>
#include <atomic>
#include <windows.h>
#define NUM_THREADS 4
std::atomic<bool> g_abExit(false);
DWORD WINAPI thread_func (LPVOID num)
{
while (!g_abExit.load(std::memory_order_acquire))
{
printf("*** THREAD #%02u: This is the bug, it's not a feature!\n",(UINT)num);
Sleep(1);
}
return 0;
}
int main()
{
HANDLE threads[NUM_THREADS];
printf("Enter q to quite...\n");
Sleep(500);
for (int i=0; i<NUM_THREADS; ++i)
if (!(threads[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)thread_func,(LPVOID)i,0,NULL))) return -1;
while (getch()!='q');
g_abExit.store(true,std::memory_order_release);
for (int i=0; i<NUM_THREADS; ++i)
WaitForSingleObject(threads[i],INFINITE);
return 0;
}
我正在使用 MinGW GCC 编译器版本 9.2.0(构建 2)。我默认为 C++ 标准编译(我不知道默认情况下 MinGW 使用什么标准,我没有找到如何查看)并且我得到了预期的正确结果:
Enter q to quite...
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
但是,当使用 -std=c++17 选项编译时,所有输出线程安全崩溃,导致一团糟:
Enter q to quite...
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a f*** THREAD #00: This is the bug, it's not a feature!
eature*** THREAD #!
01: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a featu*** THREAD #re!
01: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a featu*** THREAD #03: This is the bre!
ug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #*03: This is the bug, it's not a feature!
** THREAD #02: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #0*1:** THThisR iEAD #00s the bu: This is the bg, ugit, it's not a fea's not a feature!
ture!
*** THREAD #02: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
*** THREAD #00: This is the bug, it's not a feature!
*** THREAD #01: This is the bug, it's not a feature!
*** THREAD #03: This is the bug, it's not a feature!
请向我解释为什么会这样?由于哪个版本的 C++ 标准具有 printf() 函数不再是线程安全的,为什么?有没有办法在不编写自己的拐杖选项(例如,使控制台输出线程安全的编译器选项)的情况下恢复线程安全?
PS我读到了flockfile()、funlockfile()函数,试过了,但MinGW写道它们是“未声明的”。虽然使用它们也是一个马马虎虎的选择,但我仍然希望 printf() 本身来处理阻塞......
标准和书籍中没有任何地方说 printf 的结果不能被洗牌。只能保证不会损坏任何东西并且程序不会崩溃。如果您希望所有内容都严格连续打印 - 挂起互斥锁(在某些情况下会花费大量时间)或使用缓冲制作更复杂的系统。
非常感谢您的澄清!好吧,事实证明,除了使用互斥锁(或临界区)编写您自己的 printf() 版本外,别无他法……
可能不是一个非常快速的方法,但出于调试目的,它会做。