我们有一个 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 的整个函数块构建一个锁,所以我看不出提供这种非阻塞函数的意义。
有人可以向我解释这些锁定机制,因为我认为我们的偏执锁定方案会浪费一些性能吗?
先感谢您!