我正在开发一个程序,它使用多个std::ifstream
来读取二进制文件,每个线程一个std::ifstream
。现在我需要知道,如果std::ofstream
在Windows和Linux上是线程安全的,那么在同一个文件中写入。我只使用一个std::ofstream
并使用多个线程
我正在使用每个线程读取不同的块,并使用seekp()
和write()
在输出文件中写入这些块。目前它对我有用,但它是否对大文件有问题。
std::ofstream
线程是否安全?
答案 0 :(得分:8)
如果我没有误解你 - 不,标准库中没有任何东西是线程安全的(除了std::thread
特定的东西,当然(来自C ++ 11及更高版本))。您需要其他同步。
更多 - 如果有多个进程,读取/写入这些文件,则需要锁定文件,以同步访问。
答案 1 :(得分:6)
从C++ standards(输入/输出库线程安全):
27.1.3线程安全[iostreams.thread-safety]
并发访问流对象[string.streams,file.streams],流缓冲区对象 多个线程的[stream.buffers]或C Library stream [c.files]可能会产生数据 race [intro.multithread]除非另有说明[iostream.objects]。 [注:数据竞赛 导致未定义的行为[intro.multithread]。
答案 2 :(得分:2)
是。它是。
对于Windows: 从Windows上的多个线程写入fstream是安全的。请参阅msdn文档:Thread Safety in the C++ Standard Library
对于Linux: 简而言之,它是。从document of libstdc++:"如果您的平台的C库是线程安全的,那么您的fstream I / O操作将是最低级别的线程安全"。您平台的C库线程是否安全?是。 POSIX标准要求C stdio FILE *操作(例如fread / fwrite)是原子的,glibc是这样做的。
答案 3 :(得分:0)
我编写了一个小程序来验证 std::ifstream
的线程安全性
和 std::ofstream
https://github.com/rmspacefish/rpi-file-concurrency 。我已经在 Linux 桌面主机和 Raspberry Pi 上进行了测试。程序启动两个线程,一个写线程和一个读线程,有文本模式和二进制模式。
在文本模式下,我在写线程中写两行,读线程试图读两行。对于文本模式,我得到以下输出:
Concurrent file access test
Write Open Fail Count: 0
Write Count: 191090
Write Fail Count: 0
Read Open Fail Count: 0
Read Count: 93253
Read One Line Count: 93253
Read Both Lines Count: 93253
Faulty Read Count: 0
EOF Count: 0
Fail Count: 0
Finished.
所以这对于 Linux 来说似乎是线程安全的。对于二进制模式,我正在以由多个字段(如字符数组、各种大小的整数等)组成的结构形式编写二进制块。我有两个以交替循环写入的状态。在阅读器线程中,我检查数据的一致性(不一致的状态或更糟,错误的值)。在这里我得到以下结果
Concurrent file access test
Write Open Fail Count: 0
Write Count: 0
Write Fail Count: 0
Read Open Fail Count: 0
Read Count: 0
Blob in state one read: 25491
Blob in state two read: 24702
Blob in invalid state: 0
Faulty Read Count: 0
EOF Count: 91295
Fail Count: 91295
Finished.
我在调用 read
后检查了错误标志(这很重要)。如果没有错误标志,则以一致的方式读取状态。对我来说,它看起来是线程安全的。
线程安全可能仍然依赖于实现,但至少对于 Linux/GCC,文件访问似乎是线程安全的。我仍将在 Windows 上使用 MSVC 进行测试,但 Microsoft 指定这也应该是线程安全的。