单例模式:确保一个类只有一个实例,且提供一个全局访问点
注意问题:
- 多线程安全
- 资源申请时机
- 性能问题
sig.h
#include <iostream>
#include <pthread.h>
using namespace std;
// 提前申请好资源,不会有竞态
class MySgn {
public:
static MySgn* get_instance() { // 此处注意
return _my_sgn;
}
void say_hi() {
cout << "hell world from MySgn" << endl;
}
protected: // 此处注意
MySgn() {}
private: // 此处注意
MySgn(const MySgn&);
MySgn& operator=(const MySgn&);
private:
static MySgn* _my_sgn;
};
MySgn* MySgn::_my_sgn = new (std::nothrow) MySgn(); // 此处注意
// 延迟资源申请,double check + 锁
class MyFullSgn {
public:
static MyFullSgn* get_instance() { // 此处注意
if (_my_full_sgn == NULL) {
pthread_mutex_lock(&mutex);
if (_my_full_sgn == NULL) {
_my_full_sgn = new (std::nothrow) MyFullSgn();
}
pthread_mutex_unlock(&mutex);
}
return _my_full_sgn;
}
void say_hi() {
cout << "hell world from MyFullSgn" << endl;
}
protected: // 此处注意
MyFullSgn() {}
private: // 此处注意
MyFullSgn(const MyFullSgn&);
MyFullSgn& operator=(const MyFullSgn&);
private:
static pthread_mutex_t mutex;
static MyFullSgn* _my_full_sgn;
};
pthread_mutex_t MyFullSgn::mutex; // 此处注意
MyFullSgn* MyFullSgn::_my_full_sgn = NULL; // 此处注意
- test.cpp
#include <iostream>
#include <sig.h>
using namespace std;
int main() {
MySgn::get_instance()->say_hi();
MyFullSgn::get_instance()->say_hi();
return 0;
}
2017-08-09更新 增加mutex资源管理
#include <iostream>
#include <pthread.h>
using namespace std;
class MutexLock {
public:
MutexLock() {
pthread_mutex_init(&_mutex, NULL);
}
~MutexLock() {
pthread_mutex_destroy(&_mutex);
}
void lock() {
pthread_mutex_lock(&_mutex);
}
void unlock() {
pthread_mutex_unlock(&_mutex);
}
private:
pthread_mutex_t _mutex;
};
class MutexLockGuard {
public:
explicit MutexLockGuard(MutexLock& mutex_lock) :
_mutex_lock(mutex_lock)
{
_mutex_lock.lock();
}
~MutexLockGuard() {
_mutex_lock.unlock();
}
private:
MutexLock& _mutex_lock;
};
class MySing {
public:
static MySing* create_instance() {
if (_my_sing == NULL) {
// lock
MutexLockGuard lock(_mutex_lock);
_mutex_lock.lock();
if (_my_sing == NULL) {
_my_sing = new MySing();
}
// unlock
}
cout << "create done" << endl;
return _my_sing;
}
void say_hi() {
cout << "hi" << endl;
}
protected:
MySing() {}
private:
MySing(const MySing&);
MySing& operator=(const MySing&);
private:
static MutexLock _mutex_lock;
static MySing* _my_sing;
};
MutexLock MySing::_mutex_lock;
MySing* MySing::_my_sing = NULL;
int main() {
MySing::create_instance();
//MySing::create_instance()->say_hi();
return 0;
}