c ++:在多线程程序中写入文件

时间:2017-04-15 14:47:15

标签: c++ multithreading file file-writing

所以我有多个线程通过调用Log :: write方法写入同一个文件。

class Log
{
private:
    ofstream log;
    string file_path;
public:
    Log(string);
    void write(string);
};
Log::Log(string _file_path)
{
    file_path=_file_path;
}
void Log::write(string str)
{
    EnterCriticalSection(&CriticalSection);
    log.open(file_path.c_str(),std::ofstream::app);
    log<<str+'\n';
    log.close();
    LeaveCriticalSection(&CriticalSection);
}

如果线程同时调用同一对象的Log :: write方法,这是否安全?

1 个答案:

答案 0 :(得分:2)

您的代码很浪费,并且不遵循C ++惯用法。

从结尾开始:是的,write是线程安全的,因为win32 CRITICAL_SECTION保护它免受并发修改。

虽然:

  1. 为什么每次打开和关闭流?这是非常浪费的事情。在构造函数中打开流并保持打开状态。析构函数将处理关闭流。

  2. 如果您想使用Win32关键部分,至少使RAII安全。创建一个包含对临界区的引用的类,将其锁定在构造函数中并在析构函数中解锁它。这种方式即使抛出异常 - 保证锁定将被解锁。

  3. 无论如何,CriticalSection的减速度在哪里?它应该是Log

  4. 的成员
  5. 你知道std::mutex吗?

  6. 为什么要按值传递字符串?这是非常无效的。然后通过const引用传递。

  7. 您对某些变量(file_path)使用snake_case,而对其他变量(CriticalSection)使用上层驼峰。使用相同的约定。

  8. str永远不是字符串变量的好名称,文件流不是日志。是实际记录的东西。 logger是一个更好的名字。在我的更正中,它只是命名为m_file_stream

  9. 更正后的代码:

    class Log
    {
    
    private:
    
        std::mutex m_lock;
        std::ofstream m_file_stream;
        std::string m_file_path;
    
    public:
    
        Log(const std::string& file_path);
        void write(const std::string& log);
    };
    
    Log::Log(const std::string& file_path):
       m_file_path(file_path)
    {
         m_file_stream.open(m_file_path.c_str());
         if (!m_file_stream.is_open() || !m_file_stream.good())
         {
            //throw relevant exception.
         }
     }
    
     void Log::write(const std::string& log)
     {
        std::lock_guard<std::mutex> lock(m_lock);
        m_file_stream << log << '\n';
     }