单例模式+多线程日志类

程序思路

想自己写一个日志类来记录一些日志信息、该日志类需要支持多线程。为了避免出现多个线程写日志文件的情况*(多个线程写文件、需要频繁加锁、解锁、写文件)*决定使用“队列”来解决多个线程写文件的问题,即多个线程往日志信息队列中放信息、一个real写文件线程负责从队列头取日志并写入文件。

主要问题和解决思路:

1、提供给使用者的接口、即使用者调用哪个函数来实现日志的记录。
2、负责写日志信息的函数(线程Dolog)。
该线程应该是在创建日志对象时就创建、这就需要对象构造时创建Dolog线程。
3、如何保证日志类只有一个实例?单例模式相关文章都有讲解。

疑问

1、在测试代码中、注释掉system(“pause”);后、主线程在子线程完成之前结束、导致日志记录不全。这种情况改怎么解决?即怎么让日志对象知道主线程将要结束、从而让写日志线程退出(发消息?信号量)?
2、在debug时、发现程序并没有进入Logger的析构函数(不是说程序在退出时会自动进行资源的回收、自动调用相关对象的析构函数吗)?想知道为什么会没有进入析构函数?如果没有进入析构函数、那么怎么对资源进行回收?

完整代码

头文件 Logger.h

#pragma once
#include <queue>
#include <string>
#include <fstream>
#include <mutex>
using namespace std;

class Logger
{
public:
	static Logger* GetInstance(){
		if (instance==nullptr){
			lock_guard<mutex> lk(instanceLock);//小粒度加锁
			if (instance==nullptr){
				instance = new Logger();
			}
		}
		return instance;
	}

	static void DoLog(void* param);
	void AddLog(string &log);
	~Logger(void);

private:
	Logger(void);  //禁止在外面创建对象
	Logger(Logger& logger);

	static Logger *instance;
	static mutex instanceLock;
	mutex      queueLock;
	queue<string> m_log_queue;
	bool m_bExit;
    std::fstream  m_logfs; //只有一个线程操作
};

实现文件 Logger.cpp

#include "Logger.h"
#include <thread>
#include <iostream>
#include <fstream>
#include <mutex>

Logger* Logger::instance = NULL;
mutex Logger::instanceLock;

Logger::Logger(void){//创建一个从queue中读数据 并写入日志文件的线程
	m_bExit = false;
	(this->m_logfs).open("log.txt", std::fstream::in | std::fstream::out | std::fstream::app);
	thread t(Logger::DoLog, this);
	t.detach();
}

void Logger::DoLog(void* param){
	Logger *pThis = static_cast<Logger*>(param);
	while (true){
		if (!pThis->m_bExit){
			unique_lock<mutex> lk(pThis->queueLock);
			if (!(pThis->m_log_queue).empty()){
				string log = pThis->m_log_queue.front();
				pThis->m_log_queue.pop();
				pThis->m_logfs << log << endl;
				cout << log << endl;
			}else{

			}
		}else
			break;
	}
}

void Logger::AddLog(string &log){
	unique_lock<mutex> lk(queueLock);
	m_log_queue.push(log);
}

Logger::~Logger(void)
{
	if (Logger::instance!=NULL){
		m_bExit = true;
		m_logfs.close();
		delete Logger::instance;
		Logger::instance = NULL;
	}
}

测试代码

int main()
{
	clock_t start, end;
	start = clock();
	for (int index=0; index<9000; index++){
		thread t(addlog, index);
		t.join();
	}
	end = clock();
	system("pause");//注释掉这一句 主线程在子线程之前就退出了
    return 0;
}

运行结果

日志写入结果

在查找多线程单例模式的相关资料时、有的资料说双重锁机制在C++下无效、先记录下链接供后续学习https://blog.youkuaiyun.com/linlin003/article/details/79012416

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值