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

What level are fread thread locks on? What level do they need to be on?

Visual Studio的fread "locks out other threads."还有一个替代版本_fread_nolock,读作"without locking other threads",应该只使用"in thread-safe contexts such as single-threaded applications or where the calling scope already handles thread isolation."

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

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

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

VS 的 ifstream.read 功能是否像普通的 fread 一样工作? (我没有看到它的无锁版本。)

fread_no_lock() 似乎在您确保文件被外部机制(可能是某种形式的互斥体)锁定后使用,然后您使用它来减少开销:相关:What's the intended use of _fread_nolock, _fseek_nolock?

这也可能回答您可能有的任何其他问题:您的硬盘驱动器可能会或可能不会同时执行超过 I/O 个操作,具体取决于硬盘驱动器的类型你有:https://superuser.com/questions/252959/which-is-faster-copying-everything-at-once-or-one-thing-at-a-time

MS 标准库实现完全支持多线程。 C++ 标准解释了这个要求:

27.2.3: Concurrent access to a stream object, stream buffer object, or C Library stream by multiple threads may result in a data race unless otherwise specified.

If one thread makes a library call a that writes a value to a stream and, as a result, another thread reads this value from the stream through a library call b such that this does not result in a data race, then a’s write synchronizes with b’s read.

这意味着如果您在流上写入,则锁定(不是文件锁定,而是对内存中流数据结构的并发访问锁定)已完成,以确保所有其他并发得到良好管理使用相同流的线程。

这种锁定开销始终存在,即使不需要。根据微软的说法,这可能有性能方面的问题:

the performance of the multithreaded libraries has been improved and is close to the performance of the now-eliminated single-threaded libraries. For those situations when even higher performance is required, there are several new features.

这就是提供_nolock函数的原因。他们直接访问流而无需线程锁定。必须格外小心地使用它,例如:

  • 如果您的应用程序是单线程的(使用相同流的另一个进程有自己的数据结构,OS 在这里管理并发)
  • 如果您确定没有两个线程使用相同的流(例如,如果您只有一个 reader 线程并且写入是在您的程序之外完成的)。
  • 如果您有其他同步机制来保护代码的关键部分。例如,如果您使用互斥锁或使用原子的线程安全非阻塞算法。

在这种情况下,流访问的附加锁不是 needed/redundant。对于文件密集型功能,可能值得使用 no_lock。

注意: 正如您所指出的:只有在进行数百万次访问的密集文件访问中才值得使用 nolock。