我使用CRITICAL_SECTION
在课堂上保护我的线程功能并做了很多
发送/接收套接字操作,一切正常,但如果线程正在写入日志文件,我就会遇到麻烦!
ħ
class ClassA
{
public:
ClassA();
~ClassA();
void run();
...
private:
CRITICAL_SECTION criticalSection;
LogFiles *m_logFiles;
...
};
CPP
ClassA::ClassA()
{
m_logFiles = new LogFiles();
InitializeCriticalSection(&criticalSection);
}
ClassA::~ClassA()
{
delete m_logFiles;
DeleteCriticalSection(&criticalSection);
}
void ClassA::run()
{
EnterCriticalSection(&criticalSection);
// do some stuff
m_logFiles->WriteToFile(message);
// do some stuff
m_logFiles->WriteToFile(message);
LeaveCriticalSection(&criticalSection);
}
Logfile不包含所有信息(仅包括来自4个线程中的2个的数据)或覆盖的行(2个线程同时写入)!
所以我想我还必须在LogFiles中保护WriteToFile方法?!
感谢您提供任何帮助和/或示例!
答案 0 :(得分:5)
因为CRITICAL_SECTION
是一个实例变量,所以每个ClassA
对象实际上都有自己独立的互斥锁。因此,锁定互斥锁的一个对象(也就是进入临界区)不会阻止任何其他对象对其私有互斥锁执行相同操作,并且公共日志文件资源完全不受保护。
你可以通过使CRITICAL_SECTION
类静态或其他全局化,并在程序启动期间初始化它来解决这个问题。
更好的选择可能是LogFiles
类维护自己的CRITICAL_SECTION(甚至更好,它管理的每个日志文件都有一个),并且WriteToFile()
函数显式锁定/解锁(在调用时内部也称为进入/离开。这样资源可以保护自己,而不是明确要求其用户这样做。因此它总是表现正常,它会降低LogFile
类用户的负担。
答案 1 :(得分:0)
使用互斥锁(如win32的CRITICAL_SECTION)包装对日志文件的访问,或使用单独的线程写入日志文件条目。换句话说,就多线程而言,您提供的草图是正确的。
但您的代码还存在其他重大问题。首先,停止使用指针,特别是不要编写类似“Type * t = new Type();”的Java / C#代码。到处都是。这只会增加复杂性并导致内存泄漏。其次,您必须控制自定义类型的复制和分配。例如,类ClassA是可复制的,但实例不是独立的,这会导致更微妙的错误(悬空指针,内存泄漏等)。
如果修复C ++问题没有帮助,请考虑将代码拆分为演示问题的最小示例并在此处发布。