fread线程锁定在什么级别?他们需要达到什么水平?

时间:2015-04-25 21:21:25

标签: c++ c multithreading io locking

Visual Studio的fread“锁定了其他线程。”有一个备用版本_fread_nolock,它读取“不锁定其他线程”,它只能用于“线程安全的上下文中,例如单线程应用程序或调用范围已处理线程隔离。”

即使在阅读了关于这两者的其他有些相关的讨论之后,如果锁定fread实现是在特定的FILE结构,特定的实际文件或者对完全不同的文件的所有fread调用上,我会感到困惑。

如果使用nolock版本,您需要提供什么级别的锁定?并行多个线程可以读取单独的文件而无需任何锁定吗?并行多个线程可以写入单独的文件而不进行任何锁定吗?或者是否涉及会损坏的全局或静态变量?

因此,通过使用nolock版本,您是否能够实现更好的I / O吞吐量(如果您不是不必要地移动磁头,例如读取单独的驱动器或SSD驱动器),或者是潜在的收益将冗余锁减少到一个锁(这应该可以忽略不计。)

VS'ifstream.read函数是否像常规fread一样工作? (我没有看到它的nolock版本。)

2 个答案:

答案 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}}