天天看点

设计模式 之美 -- 单例模式

为什么要使用单例?

一个类只允许创建一个对象或者实例。

背景简介:使用多线程并发访问同一个类,为了保证类的线程安全,可以有两种方法:
  1. 将该类定义为单例模式,即该类仅允许创建一个实例
  2. 为该类的成员函数添加类级别的锁

举例:

一个向指定文件写入日志的类,为了保证该类并发调用时写入文件的日志不会覆盖,需执行以上操作。

单例模式的几种经典的实现方式:

  • 饿汉式

    在类的加载期间,将静态实例初始化好,所以实例的创建是线程安全的。但是这样的方式不支持延迟加载,且每加载一个实例都会重新初始化一次,开销较大。

  • 懒汉式

    懒汉模式相对于饿汉模式的优点是支持延迟加载(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;
}