在多线程应用程序中控制对输出的访问

Posted

技术标签:

【中文标题】在多线程应用程序中控制对输出的访问【英文标题】:Controlling access to output in multi-threaded applications 【发布时间】:2010-01-04 00:12:37 【问题描述】:

我有一个创建作业队列的应用程序,然后多个线程执行这些作业。通过执行它们,我的意思是它们使用作业字符串调用 system()。

问题是标准输出的输出看起来像问题底部的输出。我希望每个应用程序运行分开,所以输出看起来像:

弗拉克 1.2.1 ... ... ... 弗拉克 1.2.1 ... ... ... 等等

我正在使用我无法控制的程序,因此无法将 IO 包装在互斥体中。

如何让输出看起来像上面那样?

ffllaacc 11..22..11,, CCooppyyrrighhtt ((CC)) 2000,2001,2002, 2003,220004,2
005,0200,0260,0210,0270 0 2J,o2s0h0 3C,o2a004,2005,2l0s0o6n,
007f l aJco scho mCeosa lwsiotnh
 AfBl
OcL UcfTolEmaLecYs 1Nw.Oi2t .hW1 A,AR BRCSAoONpLTyUYrT.iE gL hYTt h Ni(OsC )W
i AsR2 R0fA0rN0eT,eY2 .0s 0o 1fT,th2wi0as0r 2ei,,s2 0af0nr3de, e2y 0os0uo4 f,at
2rw0ea0
e,,2 0wa0en6ld,c 2oy0mo0eu7 ta or J eor
hd iCswotearllicsbooumnte
 tiotf lruaencdd iecsrot mrceiesbr utwtaieit nhi tcA oBunSndOdiLetUriT oEcnLes
年。 t Na OiT nyW pacero Rn`AdfNilTtaYic.o' n sfT.oh ri sTd yeiptsea if`lrfsel
.ea
s
'f tfwor adreet,a iandl sy.ou
一种
e
欢迎在特定条件下重新分发。输入“flac”了解详情。

【问题讨论】:

【参考方案1】:

而不是使用 system().. 你可以使用popen()。 然后,在父程序中读取每个子程序的输出,并用它做你想做的事情(例如,在输出每一行时同步一些互斥锁)。

【讨论】:

【参考方案2】:

正如 pnm 指出的那样,popen() 可能是最好的方法。您仍然必须存储您通过管道读取的所有内容,最后将其写入您计划保存的任何位置,而不会将其与其他 popen() 调用的输出穿插。

一种更丑陋、效率更低但可能更简单的方法是设置您的 system() 作业以将其输出重定向到文件。然后,您可以有一个线程在 system() 调用完成后传递文件名,将文件内容全部附加到您的输出并删除临时文件。

或两者兼而有之。使用popen(),将管道读取的结果存储在内存中某处,当popen调用完成时将内存地址传递给输出线程,等等。

【讨论】:

【参考方案3】:

除了 pnm 和 Duck 编写的内容之外,您还应该查看外部程序的手册页,并查看它们如何让您抑制不必要的输出。

最后,你可以通过 shell 抑制输出,例如

system("flac ... > /dev/null"); 甚至是标准输出和标准错误:system("flac ... 2>&1");

【讨论】:

【参考方案4】:

我认为 popen() 是最好的解决方案,但它可能需要一些工作。

我的快速解决方案可能是将每个应用程序的输出重定向到一个 tmp 文件。 然后在所有线程完成后将 tmp 文件复制到标准输出。

system("plop > tmp1");

【讨论】:

以上是关于在多线程应用程序中控制对输出的访问的主要内容,如果未能解决你的问题,请参考以下文章

在多线程应用程序中设置硬件断点不会触发

valgrind 在多线程套接字程序中停止

Windows线程同步详解

为啥在多线程应用程序 C++ 中没有发生同步

SQLite在多线程并发访问的应用

关于js单线程(转载)