C++实现线程安全单例类(可运行)
心血来潮手撕一下线程安全的单例类,做项目的时候写过单例,今天自己动手写发现之前写的并不对。下面参考了小林 coding 的代码,针对加锁的懒汉模式,自己加了一个 AutoRelease 的内部类,可以自动释放单例类的实例资源。
加锁-懒汉模式
懒汉模式:系统运行中实例并不存在,只有当需要使用该实例时,才会去创建并使用实例。
#include <iostream>
#include <thread>
#include <mutex>
#include <unistd.h>
using namespace std;
class Singleton {
public:
static Singleton* get_instance();
void print();
private:
friend class AutoRelease;
Singleton();
~Singleton();
Singleton(const Singleton& signal) = delete;
const Singleton& operator=(const Singleton& signal) = delete;
private:
static Singleton *m_Instance;
static std::mutex m_Mutex;
private:
class AutoRelease {
public:
AutoRelease() {
std::cout << "AutoRelease()" << std::endl;
}
~AutoRelease() {
std::unique_lock<std::mutex> lock(m_Mutex);
if (m_Instance) {
delete m_Instance;
m_Instance = nullptr;
}
std::cout << "~AutoRelease()" << std::endl;
}
};
private:
static AutoRelease m_At;
};
Singleton *Singleton::m_Instance = nullptr;
std::mutex Singleton::m_Mutex;
Singleton::AutoRelease Singleton::m_At;
Singleton* Singleton::get_instance() {
if (m_Instance == nullptr) {
std::unique_lock<std::mutex> lock(m_Mutex);
if (m_Instance == nullptr) {
m_Instance = new Singleton;
}
}
return m_Instance;
}
void Singleton::print() {
std::cout << "addr: " << this << std::endl;
}
Singleton::Singleton() {
std::cout << "Singleton()" << std::endl;
}
Singleton::~Singleton() {
std::cout << "~Singleton()" << std::endl;
}
// operator func
void test() {
Singleton::get_instance()->print();
}
int main() {
// create three threads
thread t1(test);
thread t2(test);
thread t3(test);
// threads joined
t1.join();
t2.join();
t3.join();
return 0;
}
局部静态变量-懒汉模式(推荐)
在 C++11 内部静态变量是线程安全的,该方法实现的代码量最少。
#include <iostream>
#include <thread>
#include <mutex>
#include <unistd.h>
using namespace std;
class Singleton {
public:
static Singleton& get_instance();
void print();
private:
Singleton();
~Singleton();
Singleton(const Singleton& signal) = delete;
const Singleton& operator=(const Singleton& signal) = delete;
};
Singleton& Singleton::get_instance() {
static Singleton singal; // static var
return singal;
}
void Singleton::print() {
std::cout << "addr: " << this << std::endl;
}
Singleton::Singleton() {
std::cout << "Singleton()" << std::endl;
}
Singleton::~Singleton() {
std::cout << "~Singleton()" << std::endl;
}
// operator func
void test() {
Singleton::get_instance().print();
}
int main() {
// create three threads
thread t1(test);
thread t2(test);
thread t3(test);
// threads joined
t1.join();
t2.join();
t3.join();
return 0;
}
饿汉模式
饿汉模式:在程序运行时就创建实例,需要使用的话可直接调用,本身就是线程安全的。
#include <iostream>
#include <thread>
#include <mutex>
#include <unistd.h>
using namespace std;
class Singleton {
public:
static Singleton* get_instance();
void print();
private:
friend class AutoRelease;
Singleton();
~Singleton();
Singleton(const Singleton& signal) = delete;
const Singleton& operator=(const Singleton& signal) = delete;
private:
static Singleton *g_Instance;
private:
class AutoRelease {
public:
AutoRelease() {
std::cout << "AutoRelease()" << std::endl;
}
~AutoRelease() {
if (g_Instance) {
delete g_Instance;
g_Instance = nullptr;
}
std::cout << "~AutoRelease()" << std::endl;
}
};
private:
static AutoRelease m_At;
};
/* create an instance when code runs */
Singleton *Singleton::g_Instance = new Singleton;
Singleton::AutoRelease Singleton::m_At;
Singleton* Singleton::get_instance() {
return g_Instance;
}
void Singleton::print() {
std::cout << "addr: " << this << std::endl;
}
Singleton::Singleton() {
std::cout << "Singleton()" << std::endl;
}
Singleton::~Singleton() {
std::cout << "~Singleton()" << std::endl;
}
// operator func
void test() {
Singleton::get_instance()->print();
}
int main() {
// create three threads
thread t1(test);
thread t2(test);
thread t3(test);
// threads joined
t1.join();
t2.join();
t3.join();
return 0;
}
#C++##暑期实习#
查看13道真题和解析