C++ 在多线程环境(C+;+;)中读/写文件的最佳方式

C++ 在多线程环境(C+;+;)中读/写文件的最佳方式,c++,multithreading,file-io,C++,Multithreading,File Io,我有一个读写文件的多线程程序。一个线程接收数据并将其写入文件。每250 Mb的数据,就会创建一个新文件。多个其他线程可以读入这些文件以检索数据。我使用C++ STD文件流。 为了防止出现问题,我当前的实现对同一个文件使用了两个文件描述符:一个用于读取器,另一个用于编写器。互斥体可同时防止多个访问,并且每次互斥体所有者需要时,文件描述符位置都会移动 我真的需要能够尽可能快地读取文件,而互斥锁并不能真正帮助我 首先,我想知道读取和写入文件是否安全,或者同时进行多次读取(在每个平台上)。 其次,如果是

我有一个读写文件的多线程程序。一个线程接收数据并将其写入文件。每250 Mb的数据,就会创建一个新文件。多个其他线程可以读入这些文件以检索数据。我使用C++ STD文件流。 为了防止出现问题,我当前的实现对同一个文件使用了两个文件描述符:一个用于读取器,另一个用于编写器。互斥体可同时防止多个访问,并且每次互斥体所有者需要时,文件描述符位置都会移动

我真的需要能够尽可能快地读取文件,而互斥锁并不能真正帮助我

首先,我想知道读取和写入文件是否安全,或者同时进行多次读取(在每个平台上)。 其次,如果是的话,我想知道硬盘的“磁盘读写头”这样的硬件是如何安全的。该软件一直在磁盘上工作以保存数据,我不希望我的算法减少太多硬盘使用时间(已经很短)


感谢您的帮助

多线程读取同一文件没有问题

现在,如果我正确理解了您的描述,您不会修改已经写入的数据,您只需不断地将数据追加到文件中,直到达到250Mb,然后继续在新文件上写入

如果是这种情况,您可能根本不需要互斥。例如,您可以将整个“文件”保存到内存中,直到达到250mb,然后才将其全部写入磁盘,这样您就知道磁盘上的任何文件都不会再被写入,并且可以无需担心地自由读取。对于仍在写入的文件,您可以使用一个全局整数来保存已写入的字节数(或字符串或您使用的任何内容),并且读取线程受该整数的限制,该整数不需要锁,只要您仅在写入数据后更新该整数即可。(因为您说过只有1个线程写入数据)


简单地读取整数不会损坏它,即使它是由多个线程同时执行并且由单个线程写入的,因此这将确保您的读卡器线程不会读取超出限制,并且该限制始终是安全和一致的,而writer线程可以在一个区域中和平地写入数据,该区域保证在完成之前不会被读取线程打扰


至于您的第二个问题,如果您确实能够将当前正在写入的文件完全保留在内存中,那么这将节省一些HDD使用量和时间。此外,请记住,大多数现代硬盘都有32Mb+的缓存,因此并非每次读写都会直接命中硬盘本身,除非有大量线程一直在读取随机文件及其随机部分。如果是这样的话,您可能无法为HDD提供太多帮助。如果不是这样的话,也没什么好担心的,因为操作系统和缓存会做他们应该做的:)

1件事:不要担心硬盘的使用模式——操作系统会处理好的。但是,是的,如果您显著增加HDD i/o,那么无论发生什么情况,您都会减少其寿命2-如果您希望它尽可能快,请查看RAM磁盘,甚至只是将数据加载到内存中。RAM很便宜,所以试着把它都放在里面。回答你的第一个问题——是的,如果你有正确的锁定逻辑,它是安全的。如果读操作依赖于写操作,则在写操作进行时不进行读操作,等等。全局互斥锁,
std::fstream
。。。基本上,这是一个列表,上面列出了如果你想快速的话不应该做的事情。要做到如此快速,你要么使用一个共享内存,要么为每个读卡器使用一个管道,这是你能得到的最快的速度。“读取整数不能破坏它,即使它是由多个线程同时完成的,并且是由一个线程编写的”-这不是真的。您将在C++03和C++11上获得未定义的行为。此处至少需要一个原子整数。未定义的行为如中所示,如果读取与写入同时完成,则未定义读取是检索整数的旧值还是新值。在这种情况下它们都是安全的。不。未定义的行为如:数据竞争,任何事情都可能发生。你可以看到任何价值。特别是,您可能会看到一个从未实际写入的值(§1.10.21,ISO/IEC 14882:2011)。对,就像整数溢出一样。他希望尽可能快地完成这件事——在他的场景中,就是这样。虽然我会告诉你,与他读写数据的时间相比,原子开销可能没有什么意义。当两个文件在同一个硬盘上时,在安全的情况下同时从不同的线程读取这两个文件,通常也会很慢,因为驱动器会在这两个驱动器之间来回搜索超过需要的次数。您可能希望每个硬盘上有一个互斥器来控制搜索的频率。