stdout线程安全在Linux上的C?

在Linux上使用printf线程安全写入标准输出? 那么使用底层write命令呢?

它不是由C标准规定的 – 它取决于你的C标准库的实现。 事实上,C标准甚至没有提到线程,因为某些系统(如embedded式系统)没有multithreading。

在GNU实现( glibc )中,处理FILE*对象的stdio中的大多数高级函数都是线程安全的。 那些通常不会unlocked的名称(例如getc_unlocked(3) )。 但是,线程的安全性在每个函数的调用级别上:例如,如果您对printf(3)进行多个调用,那么每个调用都保证以primefaces方式输出,但其他线程可能会在调用printf() 。 如果要确保一系列I / O调用以primefaces方式输出,可以用一对flockfile(3)/funlockfile(3)调用来lockingFILE句柄。 请注意,这些函数是可重入的,因此您可以在它们之间安全地调用printf() ,即使printf()本身调用flockfile() ,也不会导致死锁。

write(2)等底层的I / O调用应该是线程安全的,但是我不是100%确定的, write()会调用内核来执行I / O操作。 这个怎么发生取决于你正在使用的内核。 它可能是sysenter指令,或者旧系统上的int (中断)指令。 一旦进入内核,就要由内核来确保I / O是线程安全的。 在一个testing中,我只是用Darwin Kernel Version 8.11.1做的, write(2)似乎是线程安全的。

是否将其称为“线程安全”取决于您对线程安全的定义。 POSIX需要使用stdio函数来使用locking,所以如果从多个线程同时使用printf ,程序不会崩溃,损坏FILE对象状态等。 然而,所有stdio操作都是通过重复调用fgetcfputc来正式指定的,所以没有大规模的primefaces性保证。 也就是说,如果线程1和2同时尝试打印"Hello\n""Goodbye\n" ,则不能保证输出将是"Hello\nGoodbye\n" "Goodbye\nHello\n" "Hello\nGoodbye\n""Goodbye\nHello\n" "Hello\nGoodbye\n" "Goodbye\nHello\n" 它也可以是"HGelolodboy\ne\n" 在实践中,大多数实现会为整个更高级别的写入调用获取一个锁,因为它更高效,但是您的程序不应该这样做。 可能会有angular落的情况下,这没有完成; 例如一个实现可能完全忽略locking未缓冲的stream。

编辑:关于primefaces性的上述文本是不正确的。 POSIX保证所有的stdio操作都是primefaces操作,但是flockfile的文档中隐藏了保证: http : flockfile

引用(FILE *)对象的所有函数的行为就像在内部使用flockfile()和funlockfile()来获得这些(FILE *)对象的所有权一样。

您可以自己使用flockfileftrylockfilefunlockfile函数来实现大于单一函数调用的primefaces写入。

它们都是线程安全的,以至于如果多个线程在相同的文件描述符上调用它们,应用程序不会崩溃。 但是,如果没有一些应用程序级别的locking,则可以将任何写入的内容交错。

这是线程安全的; printf应该是可重入的,并且不会在程序中造成任何奇怪或损坏。

你不能保证你从一个线程的输出不会从另一个线程的输出中途开始。 如果你关心的是,你需要开发自己的locking输出代码,以防止多重访问。

自从这个问题被问及(最后回答)以来,C得到了一个新的标准。

C11现在提供了multithreading支持,并解决了stream的multithreading行为:

§7.21.2stream

每个stream都有一个关联的锁,当多个执行线程访问一个stream时,用来防止数据 竞争 ,并限制多个线程执行的stream操作的交错 。 一次只能有一个线程持有这个锁。 锁是可重入的:单个线程可以在给定的时间多次保持锁。

所有读取,写入,定位或查询stream位置的函数在访问stream之前lockingstream。 访问完成后,它们释放与stream关联的锁。

所以,使用C11线程的实现必须保证使用printf是线程安全的。

是否保证了primefaces性(如无交织1 )是一目了然的,因为这个标准谈到了限制交织,而不是防止 ,它是数据竞赛所要求的。

我倾向于保证。 该标准提到了限制交织,因为一些不改变结果的交织仍然被允许发生; 例如, fwrite一些字节,然后再fseek一些字节,直到原始的偏移量,这样两个fwrite就是背靠背的。 这个实现可以自由地对这两个fwrite进行重新sorting,并将它们合并成一个单独的写入。


1 :以R ..的答案为例。