Visual Studio的fread“锁定了其他线程。”有一个备用版本_fread_nolock,它读取“不锁定其他线程”,它只能用于“线程安全的上下文中,例如单线程应用程序或调用范围已处理线程隔离。”
即使在阅读了关于这两者的其他有些相关的讨论之后,如果锁定fread实现是在特定的FILE结构,特定的实际文件或者对完全不同的文件的所有fread调用上,我会感到困惑。
如果使用nolock版本,您需要提供什么级别的锁定?并行多个线程可以读取单独的文件而无需任何锁定吗?并行多个线程可以写入单独的文件而不进行任何锁定吗?或者是否涉及会损坏的全局或静态变量?
因此,通过使用nolock版本,您是否能够实现更好的I / O吞吐量(如果您不是不必要地移动磁头,例如读取单独的驱动器或SSD驱动器),或者是潜在的收益将冗余锁减少到一个锁(这应该可以忽略不计。)
VS'ifstream.read函数是否像常规fread一样工作? (我没有看到它的nolock版本。)
答案 0 :(得分:3)
MS标准库实现完全支持多线程。 C ++标准解释了这个要求:
27.2.3:多个线程对流对象,流缓冲区对象或C库流的并发访问可能会导致数据 比赛,除非另有说明。
如果一个线程进行库调用,则将值写入流 因此,另一个线程从流中读取此值 通过库调用b,这样就不会产生数据 比赛,然后一个人的写与b的读数同步。
这意味着如果您在流上写入,则完成锁定(不是文件锁定,但是对内存中的流数据结构的并发访问锁定),以确保对所有其他线程使用良好的并发管理相同的流。
即使不需要,此锁定开销也始终存在。据微软称,这可能具有性能方面:
多线程库的性能得到了改进 接近现已消除的单线程的性能 库。对于那些性能更高的情况 必需的,有几个新功能。
这就是提供_nolock功能的原因。他们直接访问流而无需线程锁定。必须非常谨慎地使用它,例如:
在这种情况下,不需要/冗余用于流访问的附加锁。对于文件密集型功能,可能值得使用no_lock。
注意:正如您所指出的那样:只有使用nolock进行密集文件访问才能进行数百万次访问。
答案 1 :(得分:0)
fread_no_lock()似乎在确保文件被外部机制(可能是某种形式的互斥锁)锁定后使用,然后使用它来减少开销:相关:What's the intended use of _fread_nolock, _fseek_nolock?
这也可以回答您可能遇到的任何其他问题:根据您拥有的硬盘驱动器类型,您的硬盘驱动器可能会或者可能无法同时执行多于I / O操作:{ {3}}