为什么要使用单例?
一个类只允许创建一个对象或者实例。
背景简介:使用多线程并发访问同一个类,为了保证类的线程安全,可以有两种方法:
- 将该类定义为单例模式,即该类仅允许创建一个实例
- 为该类的成员函数添加类级别的锁
举例:
一个向指定文件写入日志的类,为了保证该类并发调用时写入文件的日志不会覆盖,需执行以上操作。
单例模式的几种经典的实现方式:
-
饿汉式
在类的加载期间,将静态实例初始化好,所以实例的创建是线程安全的。但是这样的方式不支持延迟加载,且每加载一个实例都会重新初始化一次,开销较大。
-
懒汉式
懒汉模式相对于饿汉模式的优点是支持延迟加载(C++ 种的动态绑定),只有实例化的时候才知道该对象的实例。但是会导致出现频发加锁,释放锁造成效率底下 的问题。
-
双重检测
双重检测既支持延迟加载,又支持高并发的单例实现方式。
-
静态内部类
JAVA支持的静态内部类实现单例。这种实现方式既支持延迟加载,也支持高并发实例,实现起来也比双重检测简单。
-
枚举
最简单的实现方式,基于枚举实现的单例。通过枚举类型本身的特性,保证了实例创建的线程安全性和实例的唯一性。
C语言单例模式的实现:
饿汉模式
csingleton.h
#ifndef CSINGLETON_H
#define CSINGLETON_H
#include <stdlib.h>
typedef struct {
void* (*ctor)(void *_self);
void* (*dtor)(void *_self);
void* (*createInstance)(void *self);
void *instance;
} _CSingleton;
extern const void *CSingleton;
void *GetInstance(void);
#endif
csingleton.c
#include "csingleton.h"
#include <stdlib.h>
static void *csingletonCtor(void *_self) {
_CSingleton *self = _self;
self->instance = _self;
return self;
}
static void *csingletonDtor(void *_self) {
_CSingleton *self = _self;
self->instance = NULL;
return self;
}
static void *csingletonCreateInstance(void *_self) {
_CSingleton *self = _self;
self->instance = _self;
return self;
}
static _CSingleton _csingleton = {
csingletonCtor, csingletonDtor, csingletonCreateInstance, NULL
};
const void *CSingleton = &_csingleton;
void *GetInstance(void) { //当调用该函数加载类的时候进行初始化
if (NULL == ((_CSingleton*)CSingleton)->instance) {
return csingletonCtor(CSingleton);
} else {
return ((_CSingleton*)CSingleton)->instance;
}
}
main.c
#include "csingleton.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
void *ps1 = GetInstance();
void *ps2 = GetInstance();
if (ps1 == ps2) {
fprintf(stdout, "ps1 = ps2\n");
}
return 0;
}
懒汉模式
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <omp.h>
typedef struct ID{
char *name;
int id_num;
}id;
static id *_id = NULL;
/*通过锁进行并发访问时线程间竞争的控制*/
static omp_lock_t lock;
id *getInstance(){
omp_set_lock(&lock);
if(NULL != _id) {
omp_unset_lock(&lock);
return _id;
} else {
_id = (id*)malloc(sizeof(id));
assert(_id != NULL);
omp_unset_lock(&lock);
return _id;
}
}
int main(int argc, char *argv[]) {
omp_set_num_threads(20);//运行时的库函数,设置运行的线程数目
id * i1, *i2;
omp_init_lock(&lock);
{
i1 = getInstance() ;
i1->name = "Rong";
i1->id_num = omp_get_thread_num();
}
{
i2 = getInstance() ;
i2->name = "Tao";
}
omp_destroy_lock(&lock);
if(i1 == i2){
fprintf(stdout, " i1 == i2 \n");
}
fprintf(stdout, "i1->name = %s, i1->score = %d\n",i1->name, i1->id_num);
fprintf(stdout, "i2->name = %s, i2->score = %d\n",i2->name, i2->id_num);
return 0;
}
C++实现单例模式
#include <iostream>
using namespace std;
class Singleon
{
private:
Singleon()
{
cout << "Singleon()" << endl;
}
static Singleon* instance;
public:
static Singleon* GetSingleon()
{
return instance;
}
static Singleon* Destroy()
{
delete instance;
instance = NULL;
}
};
/*编译加载类的时候即初始化,静态成员编译的时候即会初始化*/
Singleon* Singleon::instance = new Singleon();
int main()
{
Singleon* sl1 = Singleon::GetSingleon();
Singleon* sl2 = Singleon::GetSingleon();
Singleon* sl3 = Singleon::GetSingleon();
cout << sl1 << endl;
cout << sl2 << endl;
cout << sl2 << endl;
system("pause");
return 0;
}
#include <iostream>
using namespace std;
class Singleon
{
private:
Singleon()
{
cout << "Singleon()" << endl;
}
static Singleon*instrance;
public:
static Singleon* GetSingleon()
{
if (NULL == instrance)
{
instrance = new Singleon();
cout << "对象创建成功" << endl;
}
else
{
cout << "对象已经创建成功,无须再建" << endl;
}
return instrance;
}
static Singleon* Destroy()
{
delete instrance;
instrance = NULL;
}
};
/*类加载的时候不进行初始化,实例化的时候进行初始化*/
Singleon* Singleon::instrance = NULL;
int main()
{
Singleon* sl1 = Singleon::GetSingleon();
Singleon* sl2 = Singleon::GetSingleon();
Singleon* sl3 = Singleon::GetSingleon();
cout << sl1 << endl;
cout << sl2 << endl;
cout << sl2 << endl;
system("pause");
return 0;
}