c++ - 如何实现线程安全的日志记录?
问题描述
我在这里实现了一个 Logging 类。
class Log : public std::streambuf, public std::ostream {
public:
Log(int severity, const char* func, int line) :
std::ostream(this), severity_(severity) {
(this->severity_ == ERROR) ? std::cout << RED << "ERROR " :
std::cout << RESET << "INFO ";
std::cout << func << " @ line# " << line << ": ";
}
int overflow(int c) {
if (this->severity_ == ERROR) {
std::cout << RED;
std::cout.put((char) c);
} else {
std::cout.put((char) c);
}
return 0;
}
~Log() {
std::cout << RESET << std::endl;
}
private:
int severity_;
};
这工作正常。但是当两个线程同时执行时,输出有时会混合在一起。我经历了几个 SO 问题,但他们都以更广泛的方式讨论了这个问题。我有这个我想修复的特定实现。我尝试添加一个全局互斥锁并以线程安全的方式调用它,但问题是该文件是一个全局头文件,因此不能在此处全局定义互斥锁变量,因为它会导致多个定义错误。有没有什么办法解决这一问题?
解决方案
我前段时间做过类似的事情。我的解决方案是添加一个成员互斥锁(m_queue_mutex
在示例中)来控制对存储要记录的字符串的成员队列的访问,使用类似的函数将字符串排入队列
void print_log(std::string& msg)
{
// Format the message here, maybe add some severity tag and line numbers
// Lock the mutex, maybe something like
// std::lock_guard<mutex_type> queue_lock{m_queue_mutex};
// Now enqueue the formatted string into the mutex
}
m_queue_mutex
防止同时访问记录器队列,因此在从队列中获取字符串进行输出时也要锁定它
我的记录器还有一个线程定期锁定队列并将内容输出到文件。这种日志记录线程方法对调用记录器的线程的影响最小,因为它消除了另一个线程的 i/o 负担。我将它用于需要良好性能的服务器守护程序应用程序。
推荐阅读
- java - 将 request.getParameterMap() 转换为带有对象列表的 bean
- ios - 为什么当我从下载文件夹中删除文件时找不到构建输入文件?
- php - 当字符串包含单引号时 PHP preg_replace() 返回 null 但否则有效
- ruby-on-rails - 安装后不显示ckeditor
- azure-cosmosdb - CosmosDB 的 Gremlin - 无法在非原始类型 GraphTraversal 上创建 ValueField
- python-3.x - Facebook Messenger bot 的日期选择器 webview - 无法将字段值带回 bot 的输入字段
- php - 检查点防火墙实施后的会话交换
- java - FileReader 和 ActionListner 之间的同步问题,FileReader 在我可以给他任何勇气之前给出空指针;
- apache-spark - 从长转换为时间戳以插入数据库
- docker - 从 jwilder/nginx-proxy 提供静态文件