多线程代码中的文件I / O问题

时间:2013-09-26 11:45:58

标签: c++ multithreading winapi critical-section

我使用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方法?!

感谢您提供任何帮助和/或示例!

2 个答案:

答案 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 ++问题没有帮助,请考虑将代码拆分为演示问题的最小示例并在此处发布。