多线程单例

/// <summary>
/// 适用于在多线程的情况下保证只有一个实例化对象的情况
/// </summary>
// 双重锁定单例
public sealed class Singleton
{
	// 定义一个类对象,用于内部实现
	private static Singleton myInstance;

	//const和readonly有什么区别?
	//const关键字用来声明编译时的常量
	//readonly用来声明运行时的常量
	// 变量标记为 readonly,第一次引用类的成员时创建实例
	private static readonly object lockRoot = new object ();

	// 设置构造方法为私有,这样就不能在外部实例化类对象了
	private Singleton ()
	{
	}

	// 实例化对象的方法
	public static Singleton GetInstance ()
	{
		// 这里面使用两个判断是否为null的原因是,我们不需要每次都对实例化的语句进行加锁,只有当对象不存在的时候加锁就可以了
		if (myInstance == null) {
			// 锁定的作用就是为了保证当多线程同时执行这句代码的时候保证对象的唯一性
			// 锁定会让同时执行这段代码的线程排队执行
			// lock里面需要用一个已经存在的对象来判断,所以不能使用myInstance
			lock (lockRoot) {
				// 这里还需要一个判断的原因是,如果多线程都通过了外层的判断进行排队
				// 那将会实例化多个对象出来,所以这里还需要进行一次判断,保证线程的安全
				if (myInstance == null) {
					myInstance = new Singleton ();
				}
			}
		}
		return myInstance;
	}
}

### 实现多线程安全的日志类 在C++中,实现一个线程安全的日志类通常需要结合模式的设计原则和线程同步机制。以下是实现的关键点和示代码: #### 1. 线程安全的实现 C++11标准引入了局部静态变量的线程安全性保障,可以利用这一特性实现简洁且高效的线程安全模式。这种方式被称为“Meyers’ Singleton”,其特点是代码简洁且无需显式使用锁机制。 ```cpp class Logger { public: static Logger& get_instance() { static Logger instance; // 局部静态变量,C++11保证线程安全 return instance; } // 日志记录方法 void log(const std::string& message) { std::lock_guard<std::mutex> lock(mutex_); // 模拟日志记录操作 std::cout << message << std::endl; } private: std::mutex mutex_; // 私有构造函数和析构函数 Logger() {} ~Logger() {} // 禁止拷贝和赋值 Logger(const Logger&) = delete; Logger& operator=(const Logger&) = delete; }; ``` #### 2. 日志功能的线程安全性 在多线程环境下,日志记录操作需要保证线程安全。通常使用互斥锁(`std::mutex`)来保护共享资源,如日志输出流。上述代码中的 `log` 方法通过 `std::lock_guard<std::mutex>` 来自动加锁和解锁,确保多个线程同时调用日志记录方法时不会发生竞争条件。 #### 3. 日志类的扩展功能 为了支持更复杂的日志管理需求,可以扩展日志类的功能,如支持日志级别、日志文件写入、时间戳记录等。以下是一个扩展示: ```cpp #include <iostream> #include <fstream> #include <mutex> #include <string> #include <ctime> enum class LogLevel { DEBUG, INFO, WARN, ERROR, FATAL }; class Logger { public: static Logger& get_instance() { static Logger instance; return instance; } void set_log_level(LogLevel level) { log_level_ = level; } void log(LogLevel level, const std::string& message, const std::string& file, int line, const std::string& function) { if (level < log_level_) return; std::lock_guard<std::mutex> lock(mutex_); std::time_t now = std::time(nullptr); char time_str[20]; std::strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", std::localtime(&now)); std::string level_str; switch (level) { case LogLevel::DEBUG: level_str = "DEBUG"; break; case LogLevel::INFO: level_str = "INFO"; break; case LogLevel::WARN: level_str = "WARN"; break; case LogLevel::ERROR: level_str = "ERROR"; break; case LogLevel::FATAL: level_str = "FATAL"; break; } // 输出日志信息 std::cout << "[" << time_str << "] [" << level_str << "] " << file << ":" << line << " - " << function << "() - " << message << std::endl; } private: LogLevel log_level_ = LogLevel::DEBUG; std::mutex mutex_; Logger() {} ~Logger() {} Logger(const Logger&) = delete; Logger& operator=(const Logger&) = delete; }; ``` #### 4. 使用示 通过宏定义简化日志调用方式,可以方便地在代码中使用日志功能。如: ```cpp #define LOG(level, message) \ Logger::get_instance().log(level, message, __FILE__, __LINE__, __FUNCTION__) ``` 使用时直接调用宏即可: ```cpp LOG(LogLevel::INFO, "This is an info message."); LOG(LogLevel::ERROR, "An error occurred."); ``` #### 5. 性能优化 在高性能场景中,频繁的加锁操作可能会影响性能。可以通过以下方式优化: - **日志缓冲**:将日志消息缓存到队列中,由独的线程负责写入文件或输出流。 - **异步日志**:采用异步方式处理日志输出,避免主线程阻塞。 - **按需加锁**:仅在实际写入共享资源时加锁,减少锁的持有时间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值