0

我在课堂上保护我的线程函数CRITICAL_SECTION并执行大量发送/接收套接字操作,一切正常,但如果线程正在写入日志文件,我就会遇到麻烦!

H

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);
}

日志文件不包含所有信息(仅来自例如 4 个线程中的 2 个的数据)或覆盖的行(2 个线程同时写入)!

所以我想我还必须保护 LogFiles 中的 WriteToFile 方法?!

感谢您的帮助和/或示例!

4

2 回答 2

5

因为CRITICAL_SECTION是一个实例变量,所以每个ClassA对象实际上都有自己的、独立的互斥体。因此,锁定互斥体的一个对象(也就是进入临界区)不会阻止任何其他对象对其私有互斥体执行相同的操作,并且公共日志文件资源完全不受保护。

您可以通过将CRITICAL_SECTION类设为静态或其他方式来解决此问题,并在程序启动期间对其进行初始化。

更好的选择可能是让LogFiles类维护自己的 CRITICAL_SECTION(或者更好的是,为它管理的每个日志文件一个),并WriteToFile()在调用时在内部显式地锁定/解锁(也就是进入/离开)它。通过这种方式,资源可以保护自己,而不是明确要求其用户这样做。因此,它将始终正确运行,并减轻LogFile班级用户的负担。

于 2013-09-26T21:50:35.670 回答
0

要么使用互斥锁(如 win32 的 CRITICAL_SECTION)包装对日志文件的访问,要么使用单独的线程来写入日志文件条目。换句话说,就多线程而言,您提供的草图是正确的。

不过,您的代码还有其他大问题。首先,停止使用指针,特别是不要编写像“Type* t = new Type();”这样的 Java/C# 代码 到处都是。这只会增加复杂性并导致内存泄漏。其次,您必须控制自定义类型的复制和分配。例如,您的 ClassA 类是可复制的,但实例不是独立的,这会导致进一步的细微错误(悬空指针、内存泄漏等)。

如果修复 C++ 问题没有帮助,请考虑将代码精简为演示问题的最小示例并将其发布在此处。

于 2013-09-26T16:09:44.420 回答