程序可以同时在同一个FILE*上调用fflush()吗?

Ser*_*tch 43 c multithreading file stdio fflush

如果多个线程同时调用fflush()同一个FILE*变量,是否会发生任何不良事件(如未定义的行为,文件损坏等)?

澄清:我不是指同时写文件.我只是说要同时冲洗它.

线程不会同时读取或写入文件(它们只在临界区内写入文件,一次一个线程).它们只在临界区外冲洗,以便更快地释放关键部分,以便让其他人完成其他工作(文件写入除外).

虽然可能发生一个线程正在写文件(在临界区内),而另一个线程正在刷新文件(在临界区之外).

250*_*501 39

C 1中的流是线程安全的2.在访问流之前需要使用函数来锁定流3.

fflush函数是线程安全的,可以随时从任何线程调用,只要该流是输出流或更新流4.


1按照现行标准,即C11.

2(引用自:ISO/IEC 9899:201x 7.21.3流7)
每个流都有一个相关的锁,用于在多个执行线程访问流时阻止数据竞争,并限制多个流执行的流操作的交错线程.一次只有一个线程可以保持此锁定.锁是可重入的:单个线程可以在给定时间多次保持锁.

3(引自来自:ISO/IEC 9899:201x 7.21.3 Streams 8)
读取,写入,定位或查询流的位置的所有函数在访问流之前锁定流.当访问完成时,它们释放与流关联的锁.可重入:单个线程可以在给定时间多次保持锁定.

4(引用自:ISO/IEC 9899:201x 7.21.5.2 fflush功能2)
如果流指向输入流或未输入最近操作的更新流,则fflush功能会导致该流的任何未写入数据要传递到主机环境以写入文件; 否则,行为未定义.

  • @cat VS甚至不符合C99. (8认同)
  • @cat Microsoft Visual C++旨在成为C++编译器,而不是C编译器.AFAIK他们在最近的版本中支持C++ 14. (3认同)
  • C流并不总是安全的.我记得不得不追查他们没有的错误.然而,如果你今天遇到这样的错误,那么你的编译器厂商就会出错. (2认同)

geo*_*car 12

该对字符流操作的POSIX.1和C语言的函数(用指针表示以文件类型的对象)都需要通过POSIX.1c在重入实现(见ISO/IEC 9945这样的方式来实现:1- 1996年,§8.2).

这个要求有一个缺点; 由于为了重入而必须在函数的实现中构建同步,因此它会带来实质性的性能损失.POSIX.1c通过引入以下C语言标准I/O函数的高性能但非重入(可能不安全)版本来解决重入(安全)和性能之间的权衡:getc(),getchar(),putc ()和putchar().不可重入的版本名为getc_unlocked(),依此类推,以强调其不安全性.

但请注意,其他人已经注意到:许多流行的系统(包括Windows和Android)都不符合POSIX标准.


chq*_*lie 9

你不应该调用fflush()输入流,它会调用未定义的行为,所以我假设流是在写或更新模式下打开的.

如果流在更新模式("w+""r+")中打开,则在调用时不能读取最后一个操作fflush().由于流以异步方式用于各种线程,因此如果进行任何读取,如果没有某种形式的进程间通信和同步或锁定,则很难确保这种情况.在更新模式下打开文件仍然有正当理由,但请确保在启动fflush线程后不执行任何读取操作.

fflush()不会修改当前位置.它只会导致任何缓冲输出写入系统.流通常由锁保护,因此fflush()在一个线程中调用不应该混淆另一个线程执行的输出,但它可能会改变系统写入的时间.如果多个线程输出相同的内容FILE*,则交错发生的顺序无论如何都是不确定的.此外,如果您使用的fseek()是同一个流的不同线程,则必须使用自己的锁来确保fseek()以下输出之间的一致性.

虽然这样做似乎没问题,但可能不推荐.fflush()在释放锁之前,您可以在每个线程中的写操作之后调用.