【问题标题】:What level are fread thread locks on? What level do they need to be on?fread 线程锁在什么级别?他们需要达到什么水平?
【发布时间】:2015-04-25 21:21:24
【问题描述】:

Visual Studio 的 fread “锁定其他线程”。还有一个替代版本 _fread_nolock,读作“不锁定其他线程”,只能在“线程安全上下文中使用,例如单线程应用程序或调用范围已经处理线程隔离的地方”。

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

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

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

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

【问题讨论】:

  • C 运行时库可以追溯到很久很久以前,早在操作系统支持线程之前。当两个线程在同一个文件上调用 fread() 时,规范从未更新说明 应该 发生什么。因此,图书馆作者必须自谋生路才能使旧规范发挥作用。不像 CRT 给了程序员另一种方式。通过尝试绕过锁,您实际上领先的几率非常低,I/O 非常慢。然而,这并非在所有情况下都是如此,例如,语言环境非常昂贵。大多数试图做正确的程序的命运都是避免 CRT。

标签: c++ c multithreading io locking


【解决方案1】:

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

27.2.3: 多个线程同时访问流对象、流缓冲区对象或 C 库流可能会导致数据 种族,除非另有说明。

如果一个线程调用了一个将值写入流的库调用 结果,另一个线程从流中读取该值 通过库调用 b 这样不会导致数据 比赛,然后 a 的写入与 b 的读取同步。

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

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

多线程库的性能得到了改进,并且 接近现已淘汰的单线程的性能 图书馆。对于那些需要更高性能的情况 需要,有几个新功能。

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

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

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

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

【讨论】:

    【解决方案2】:

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

    这也可以回答您可能有的任何其他问题:您的硬盘驱动器可能会或可能不会同时执行多个 I/O 操作,具体取决于您拥有的硬盘驱动器类型:@ 987654322@

    【讨论】:

    • 我在发帖前看到了“... O/P 说“the”(思考的意思是 fread)函数阻塞了重入调用,允许一个线程一次作为一个整体在函数中。但是,一个答案表明锁定是在 FILE* 级别。另一个答案说线程安全版本是可重入的,但是您不能使用相同的 FILE* 调用两个版本。另一个答案说使用 _nolock 版本可以获得更好的性能,但没有提到实际磁盘 I/O 是否更高,或者它是否只是绕过冗余锁。它给我留下了更多的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-14
    • 1970-01-01
    • 2014-02-25
    • 1970-01-01
    • 1970-01-01
    • 2016-06-12
    • 2010-09-14
    相关资源
    最近更新 更多