【问题标题】:What's the intended use of _fread_nolock, _fseek_nolock?_fread_nolock、_fseek_nolock 的预期用途是什么?
【发布时间】:2009-12-11 19:48:26
【问题描述】:

我们有一个 C++ 类,它基本上从二进制文件中读取和写入向量。将单个向量加载到内存中的示例读取函数如下所示:

int load (const __int64 index, T* values) const {

 int re = _fseeki64(_file, index * _vectorSize + _offsetData, SEEK_SET); 
 assert(re == 0);

 size_t read = fread(values, sizeof(T), _vectorElements, _file);
 assert(read == _vectorElements);

 return 0;}

Out 程序使用 OpenMP 进行多线程处理,并且多个线程同时访问同一个文件。为了避免由于多线程导致的问题,我们总是在 OpenMP 关键语句中包含函数调用:

#pragma omp critical {
    load(...);
}

我知道 Microsoft Visual C++ 运行时包含几个函数,如_fseek_nolock_fread_nolock_fwrite_nolock 等等...例如_fread_nolock() 函数被描述为

此函数是 fread 的非锁定版本。它与 fread 相同,只是它不受其他线程的干扰。它可能会更快,因为它不会产生锁定其他线程的开销。仅在线程安全的上下文中使用此函数,例如单线程应用程序或调用范围已处理线程隔离的情况。

现在我的问题是:我知道该函数会阻止“重入”调用,因此在其他线程返回之前没有其他线程会进入该函数。但是,我不明白为什么有必要以这种方式保护单个功能。恕我直言,所有访问/修改文件指针(代码示例中的_file)的函数都必须受到保护,因此必须是线程安全的。这需要围绕实际调用标准 C 函数 fseek 和 fread 的整个函数块构建一个锁,所以我看不出提供这种非阻塞函数的意义。

谁能解释一下这些锁定机制,因为我认为我们偏执的锁定方案会浪费一些性能?

提前谢谢你!

【问题讨论】:

  • 我忘了补充一下,我们正在讨论 Microsoft 特定的 C++ 运行时函数

标签: c++ windows multithreading fread fseek


【解决方案1】:

对于一些简单的代码,FILE * 中的锁就足够了。考虑一个基本的日志基础设施,您希望所有线程都通过一个通用的 FILE * 进行日志记录。内部锁将确保 FILE * 不会被多个线程破坏,并且由于每个日志行都应该独立,因此各个调用交错的方式无关紧要。

【讨论】:

  • 好的,这就解释了为什么 fwrite() 会锁定其他线程。 AFAIR fwrite() 移动文件指针,因此多个线程可以通过一次又一次地调用 fwrite() 将日志消息附加到文件中。我仍然看不出为什么有_fseek_nolock。这个函数总是需要第二个函数来处理文件指针。
  • 您拥有 _fseek_nolock 的原因是您是否关心性能并需要文件操作的原子序列。您使用 _lock_file() / _unlock_file() 包围一系列文件操作,以使命令原子 w.r.t。到文件。完成此操作后,您可以使用 _nolock 函数稍微减少开销。
【解决方案2】:

如果您使用 Microsoft 多线程 C 运行时,所有需要全局或静态变量的函数都可以正常工作(例如 printf 和 fread,但不要问我为什么它们需要全局变量)。但是,您仍然不能将 FILE * 结构传递给写入它的函数并期望它是线程安全的。

因此,微软的“线程安全”函数只有在它们是可重入的意义上才是线程安全的,即所有对全局变量和静态变量的访问都是通过互斥锁或类似函数完成的。但并不是说你可以使用同一个 FILE * 同时调用两个 fprintf()。

来源:http://msdn.microsoft.com/en-us/library/1bh5ewb2%28VS.71%29.aspx

【讨论】:

    【解决方案3】:

    如果您的应用程序已经保证对文件句柄的序列化访问,如果您告诉 c-runtime 绕过它自己的序列化,您可以获得更好的性能。这就是 _fread_nolock 等函数的用途。

    【讨论】:

      猜你喜欢
      • 2012-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-22
      • 2019-09-17
      • 2012-10-23
      • 2014-06-24
      • 1970-01-01
      相关资源
      最近更新 更多