使用相同的临界区对象进行读取和写入
我需要编写一个读取和写入文件的类。当我执行写入操作时,不应进行读取,反之亦然。我可以使用单个关键部分对象吗?像这样:
FileWorker.h
class FileWorker
{
public:
FileWorker();
void WriteIntoFile(const char* fileName, const char* stringToWrite);
void ReadFromFile(const char* fileName, char* stringToRead, int* stringLength);
~FileWorker();
};
FileWorker.cpp
#include <windows.h>
#include "FileWorker.h"
static CRITICAL_SECTION g_criticalSection;
FileWorker::FileWorker()
{
#ifdef WIN32APP
InitializeCriticalSection(&g_criticalSection);
#endif
}
void FileWorker::ReadFromFile(const char *fileName, char *stringToRead, int *stringLength)
{
EnterCriticalSection(&g_criticalSection);
// Do Read
LeaveCriticalSection(&g_criticalSection);
}
void FileWorker::WriteIntoFile(const char *fileName, const char *stringToWrite)
{
EnterCriticalSection(&g_criticalSection);
// Do Write
LeaveCriticalSection(&g_criticalSection);
}
FileWorker::~FileWorker()
{
#ifdef WIN32APP
DeleteCriticalSection(&g_criticalSection);
#endif
}
谢谢。
I need to write a class which reads from and writes to a file. When I do a write operation, read should not take place and also vice versa. Can I use a single critical section object for that? Like this:
FileWorker.h
class FileWorker
{
public:
FileWorker();
void WriteIntoFile(const char* fileName, const char* stringToWrite);
void ReadFromFile(const char* fileName, char* stringToRead, int* stringLength);
~FileWorker();
};
FileWorker.cpp
#include <windows.h>
#include "FileWorker.h"
static CRITICAL_SECTION g_criticalSection;
FileWorker::FileWorker()
{
#ifdef WIN32APP
InitializeCriticalSection(&g_criticalSection);
#endif
}
void FileWorker::ReadFromFile(const char *fileName, char *stringToRead, int *stringLength)
{
EnterCriticalSection(&g_criticalSection);
// Do Read
LeaveCriticalSection(&g_criticalSection);
}
void FileWorker::WriteIntoFile(const char *fileName, const char *stringToWrite)
{
EnterCriticalSection(&g_criticalSection);
// Do Write
LeaveCriticalSection(&g_criticalSection);
}
FileWorker::~FileWorker()
{
#ifdef WIN32APP
DeleteCriticalSection(&g_criticalSection);
#endif
}
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您正在谈论相同的文件进行读/写,那么您需要使用相同的关键部分(正如您当前所做的那样),否则一个线程可能正在读取该文件,而另一个线程正在写入该文件,这是正是您使用关键部分要避免的事情。
但是,按照您的 FileWorker 类当前的编写方式,您可以读取/写入任意文件,但具有单个全局临界区。在这种情况下,这仍然有效,但如果很少出现对同一文件的争用,最终会增加额外的开销。这对您来说可能是一个可以接受的权衡,具体取决于您的使用模式以及此代码的时间紧迫性。
此外,正如 Begemoth 指出的那样,如果您创建两个生命周期重叠的 FileWorker,您将会遇到单个全局关键部分的问题。您将需要类似于建议的内容,以确保您不会尝试初始化已初始化的关键部分,或删除已删除的关键部分。
If you're talking about the same file for reading/writing, then you need to use the same critical section (as you have currently done), otherwise one thread could be reading the file, while another thread is writing to it, which is exactly what you are using the critical sections to avoid.
However, the way your FileWorker class is currently written, you can read/write arbitrary files, but have a single global critical section. That still works in this scenario, but it will end up adding extra overhead if there's rarely contention for the same file. This might be an acceptable tradeoff for you, depending on your usage patterns and how time critical this code is.
Also, as Begemoth pointed out, you will have issues with a single global critical section if you create two FileWorkers with overlapping lifetimes. You'll need something similar to what was proposed to make sure you don't try to initialize a critical section that's already been initialized, or delete one that's already been deleted.
正如其他答案所指出的,当同时使用 FileWorker 的多个实例时,单个全局关键部分会导致问题。您应该使临界区成为 FileWorker 的成员,并在构造函数/析构函数中初始化/删除它。
对于锁定的实现,我建议编写一个小帮助器类来支持作用域锁定:
您可以像这样使用这个对象:
要了解它是如何工作的,请阅读RAII。
As the other answers have pointed out, a single global critical section leads to problems when using multiple instances of
FileWorker
at once. You should make the critical section a member ofFileWorker
, and initialize/delete it in the constructor/destructor.For the implementation of the locking, I would recommend writing a little helper class to support scoped locking:
You can use this object like this:
To understand how this works, read about RAII.
您需要所有线程使用相同的临界区来保护共享资源。除了构造函数和析构函数之外,代码都可以。此代码会导致未定义的行为:
因为
g_riticSection
被初始化了两次而没有中间删除。您需要添加静态成员函数来初始化和完成您的类。当您需要基于每个文件进行同步时,正确的方法是在文件 I/O 手段(HANDLE、FILE*s、std::fstream 等)之上实现抽象。例如,
此类的实例不可复制且不可分配,这一点很重要,因为必须复制关键部分。
You need to the same critical section by all threads to protect the shared resource. The code is ok except constructor and destructor. This code results to undefined behavior:
becasuse the
g_criticalSection
is initialized twice without intermediate deletion. You need to add static member functions to initialize and finalize your class.When you need to synchronize on per-file basis the right way is to implement an abstraction on top of you file I/O means (HANDLEs, FILE*s, std::fstream, etc). E.g.
Instances of this class are not copyable and not assignable this is important because critical section must be copied.