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

如果有几个线程在同一个FILE*variables上同时调用fflush() ,会发生什么不好的情况(如未定义的行为,文件损坏等)

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

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

虽然可能发生一个线程正在写入文件(在关键部分内),而另一个线程正在刷新文件(在关键部分之外)。

C 1中的stream是线程安全的2 。 在访问stream之前,需要使用函数来lockingstream3

fflush函数是线程安全的,可以随时从任何线程中调用,只要stream是输出stream或更新stream4


1根据当前的标准,即C11。

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

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

4 (引自:ISO / IEC 9899:201x 7.21.5.2 fflush函数2)
如果stream指向输出stream或没有input最近操作的更新stream,则fflush函数会将该stream的所有未写入数据传递到主机环境以写入文件; 否则,行为是不确定的。

POSIX.1c 需要 POSIX.1和C语言函数(用指向FILEtypes的对象的指针表示)来实现重入(见ISO / IEC 9945:1- 1996,§8.2)。

这个要求有一个缺点, 由于为了重入而必须build立到function的实现中的同步,所以它施加了大量的性能损失。 POSIX.1c通过引入以下C语言标准I / O函数的高性能但不可重入(可能不安全)版本来解决重入(安全)和性能之间的这种折衷:getc(),getchar(),putc ()和putchar()。 不可重入的版本被​​命名为getc_unlocked()等等,以强调它们的不安全性。

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

您不应该在inputstream上调用fflush() ,它会调用未定义的行为,所以我将假定stream在写或更新模式下打开。

如果数据stream在更新模式( "w+""r+" )下打开,则在调用fflush()时最后一个操作不能被读取。 由于stream是asynchronous使用在各种线程中的,因此如果您进行任何读取操作,没有某种forms的进程间通信和同步或locking就很难确保这一点。 仍然有一个合理的理由在更新模式下打开文件,但是确保在启动fflush线程之后不要执行任何读取操作。

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

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

很简单的答案,你可能不会这样做,因为文件有一个“当前位置”。 你如何跟踪它? 该文件打开顺序访问或随机? 在后一种情况下,您可以多次打开它(每个线程一个),然后设法保持文件结构一致。

实际的答案似乎是stream是(本意)是线程安全的,但是,如果不是这种情况,你的问题可能是fflush发生(锁外),而另一个线程正在写(关键部分)。

因此,我会使用您正在编码的虚拟机的模型,并将fflush()放入关键部分。