前言
在近日学习中发现,如果开发一个单例模式的日志系统,难免会出现多个线程记录日志的情况,这个时候线程可能导致竞争,或者始料未及的情况发生。
通过学习,如果要保证线程安全,要使用互斥锁QMutex,和QMutexLocker。
根据官方文档对这两个类进行解释:
QMutex:保证一个对象、数据结构或者代码片段在同一时间只有一个线程可以访问。经常和QMutexLocker一起使用,达到自动释放锁的效果。
QMutexLocker:是一个用来简化QMutex加锁和解锁的类。
看了具体解释,现在我来具体使用,假设我有一个Logger.h文件,在下面添加一个QMutex mutex_;
class Logger : public QObject
{Q_OBJECT
public:void log(LogLevel level, const QString& message); // 假设要这个函数线程安全// ...其他定义private:// 添加这个成员变量。QMutex mutex_;
};
然后在写入日志的函数开始就加上这么一行,就让写入操作是线程安全的了。如同注释,离开这个作用域,锁会被自动打开。
void Logger::log(LogLevel level, const QString& message)
{// 离开这个作用域时自动解锁QMutexLocker locker(&mutex_);//... 写入日志的操作
}
如果不使用QMutexLocker,那么要这样手动加锁和解锁。
void Logger::log(LogLevel level, const QString& message)
{// 加锁mutex_.lock();//... 写入日志的操作// 解锁mutex_.unlock();
}
如下,大家仔细思考就会发现,万一在写入日志过程中使用了return,函数提前结束,是不是就会出现没有解锁的情况,这肯定是不安全的。所以还是建议QMutex和QMutexLocker一起使用。
void Logger::log(LogLevel level, const QString& message)
{// 加锁mutex_.lock();//... 写入日志的操作// 假设这里不小心return了,导致没有解锁,出现不安全的情况return;// 解锁mutex_.unlock();
}