c ++:在多线程程序中写入文件
c++: Writing to a file in multithreaded program
所以我有多个线程通过调用 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方法安全吗?
您的代码很浪费,而且不遵循 C++ 习惯用法。
从头开始:是的,write
是线程安全的,因为 win32 CRITICAL_SECTION
保护它免受并发修改。
虽然:
为什么每次都打开关闭流?这是非常浪费的事情。在构造函数中打开流并保持打开状态。析构函数将处理关闭流。
如果你想使用 Win32 临界区,至少使其 RAII 安全。制作一个 class 包装对关键部分的引用,将其锁定在构造函数中并在析构函数中解锁。这样即使抛出异常——你也能保证锁会被解锁。
CriticalSection
减速到底在哪里?它应该是 Log
.
的成员
你知道std::mutex
吗?
为什么要按值传递字符串?这是非常低效的。然后通过 const 引用传递。
您对某些变量 (file_path
) 使用 snake_case,但对其他变量 (CriticalSection
) 使用大驼峰式。使用相同的约定。
str
从来都不是字符串变量的好名字,文件流也不是日志。是执行实际日志记录的东西。 logger
是一个更好的名字。在我的更正中只是将其命名为 m_file_stream
.
更正后的代码:
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';
}
所以我有多个线程通过调用 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方法安全吗?
您的代码很浪费,而且不遵循 C++ 习惯用法。
从头开始:是的,write
是线程安全的,因为 win32 CRITICAL_SECTION
保护它免受并发修改。
虽然:
为什么每次都打开关闭流?这是非常浪费的事情。在构造函数中打开流并保持打开状态。析构函数将处理关闭流。
如果你想使用 Win32 临界区,至少使其 RAII 安全。制作一个 class 包装对关键部分的引用,将其锁定在构造函数中并在析构函数中解锁。这样即使抛出异常——你也能保证锁会被解锁。
CriticalSection
减速到底在哪里?它应该是Log
. 的成员
你知道
std::mutex
吗?为什么要按值传递字符串?这是非常低效的。然后通过 const 引用传递。
您对某些变量 (
file_path
) 使用 snake_case,但对其他变量 (CriticalSection
) 使用大驼峰式。使用相同的约定。str
从来都不是字符串变量的好名字,文件流也不是日志。是执行实际日志记录的东西。logger
是一个更好的名字。在我的更正中只是将其命名为m_file_stream
.
更正后的代码:
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';
}