Jon*_*hop 3 c++ windows multithreading iostream thread-safety
从我读到的,标准输出流通常不是线程安全的.我有一个C++应用程序(基于Windows,使用Visual Studio 2005)具有非常简单的日志记录功能:
void logText(string text)
{
if(g_OutputLogEnabled && g_OutputLog.is_open())
{
string logDate = getDateStamp("%Y-%m-%d %H:%M:%S");
g_OutputLog << "[" << logDate << "]: " << text << endl;
}
cout << text << endl; // Also echo on stdout
}
Run Code Online (Sandbox Code Playgroud)
在这个例子中,g_OutputLog是一个ofstream并且g_OutputLogEnabled是一个布尔值.
我一直在我的主应用程序中使用这个小函数没有问题,但我现在想将其用途扩展到一些子线程.这些线程在工作完成后可以工作并异步打印数据.
问题:如何在此例程中添加简单的行级线程安全性?所有我真正关心的是,我的日志中的每一行都保持不变.在这种情况下,性能不是问题,但(一如既往)更快更好.
我知道我可以使用第三方日志包,但我想自己做,所以我可以学习它是如何工作的.我的多线程知识不应该是它应该是什么,我正在努力改进它.
我听过关键部分一词,我有点意识到互斥锁和信号量,但在这种情况下我会使用哪些?有一个干净,简单的解决方案吗?提前感谢任何建议.
使用范围锁定,例如:
void logText(string text)
{
if(g_OutputLogEnabled && g_OutputLog.is_open())
{
string logDate = getDateStamp("%Y-%m-%d %H:%M:%S");
boost::scoped_lock (g_log_mutex); //lock
g_OutputLog << "[" << logDate << "]: " << text << endl;
} //mutex is released automatically here
boost::scoped_lock (g_cout_log_mutex); //lock on different mutex!
cout << text << endl; // Also echo on stdout
}
Run Code Online (Sandbox Code Playgroud)
或者你可以使用,std::unique_lock如果你的编译器支持这个.
scoped_lock如果你不能使用Boost,如果你没有,你将如何实施std::unique_lock?首先定义mutex类:
#include <Windows.h>
class mutex : private CRITICAL_SECTION //inherit privately!
{
public:
mutex()
{
::InitializeCriticalSection(this);
}
~mutex()
{
::DeleteCriticalSection(this);
}
private:
friend class scoped_lock; //make scoped_lock a friend of mutex
//disable copy-semantic
mutex(mutex const &); //do not define it!
void operator=(mutex const &); //do not define it!
void lock()
{
::EnterCriticalSection(this);
}
void unlock()
{
::LeaveCriticalSection(this);
}
};
Run Code Online (Sandbox Code Playgroud)
然后定义scoped_lock为:
class scoped_lock
{
mutex & m_mutex;
public:
scoped_lock(mutex & m) : m_mutex(m)
{
m_mutex.lock();
}
~scoped_lock()
{
m_mutex.unlock();
}
};
Run Code Online (Sandbox Code Playgroud)
现在你可以使用它们了.