上篇《C语言:class="superseo">单例模式(饿汉式)》,我们介绍了单例的饿汉式实现,本文将向大家继续介绍单例的懒汉式实现方式。
懒汉式懒汉式,本意就是说这种实现像懒汉一样,不到紧要关头绝不创建对象。常用的有两种实现方式:第一种方式是把对象声明为static变量,利用static调用只初始化一次的特性实现单例,这种方式创建的单例对象在全局静态区,第二种是通过堆栈实现,当指针对象第一次调用为NULL的时候,通过malloc从堆内存中申请创建对象,其他调用时刻指针对象非NULL,不在重新创建。这种方式 创建的对象在堆区。
static方式static初始化主要借用struct初始化和static调用只初始化一次的特性。由于struct有顺序初始化和乱序初始化两种方式,所以static方式也会有两种细分。
声明typedef void File;
typedef enum BOOL
{
FALSE = 0,
TRUE = 1,
}BOOL;
typedef struct tagFileManager
{
File* (*mkFile)(const char* fileName, char const* mode);
BOOL (*rmFile)(const char* fileName);
int (*write)(File* file, const char* buf, int size);
BOOL (*exit)(const char* fileName);
BOOL (*close)(const File* file);
}FileManager;
FileManager* fileManager();
实现
FileManager* fileManager()多线程访问需要保障线程安全,C语言的static关键字不具备线程安全,只有C++11的static采用线程安全特性。
#include
#include
static File* mkFile(const char* fileName, char const* mode);
static BOOL rmFile(const char* fileName);
static int fileWrite(File* file, const char* buf, int size);
static BOOL isExit(const char* fileName);
static BOOL fileClose(const File* file);
pthread_mutex_t g_mutex= PTHREAD_MUTEX_INITIALIZER;
File* mkFile(const char* fileName, char const* mode)
{
FILE* file = NULL;
if (0 == fopen_s(&file, fileName, mode))
{
return file;
}
return NULL;
}
BOOL rmFile(const char* fileName)
{
if (isExit(fileName))
{
return !remove(fileName);
}
}
int fileWrite(File* file, const char* buf, int size)
{
return fwrite(buf, size, 1, file);
}
BOOL isExit(const char* fileName)
{
return (_access(fileName, 0) == 0);
}
BOOL fileClose(const File* file)
{
return !fclose(file);
}
FileManager* fileManager()
{
pthread_mutex_lock(&g_mutex);
// C语言乱序初始化
static FileManager fileManager = {
.exit = isExit,
.mkFile = mkFile,
.write = fileWrite,
.rmFile = rmFile,
.close = fileClose
};
// C语言顺序初始化
//static FileManager fileManager = {mkFile, rmFile,fileWrite,isExit, fileClose};
pthread_mutex_unlock(&g_mutex);
return &fileManager;
}
堆栈方式
堆栈方式就是利用运行是动态管理内存的方式,在程序真正需要对象时再创建对象,而且一旦创建成功后续访问则无需再创建,从而保证全局唯一。
声明#include
#include
typedef void File;
typedef enum BOOL
{
FALSE = 0,
TRUE = 1,
}BOOL;
typedef struct tagFileManager
{
File* (*mkFile)(const char* fileName, char const* mode);
BOOL (*rmFile)(const char* fileName);
int (*write)(File* file, const char* buf, int size);
BOOL (*exit)(const char* fileName);
BOOL (*close)(const File* file);
}FileManager;
FileManager* fileManager();
void releaseFileManager();
实现
#include
#include
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
static FileManager* g_fileManager = NULL;
static File* mkFile(const char* fileName, char const* mode);
static BOOL rmFile(const char* fileName);
static int fileWrite(File* file, const char* buf, int size);
static BOOL isExit(const char* fileName);
static BOOL fileClose(const File* file);
File* mkFile(const char* fileName, char const* mode)
{
FILE* file = NULL;
if (0 == fopen_s(&file, fileName, mode))
{
return file;
}
return NULL;
}
BOOL rmFile(const char* fileName)
{
if (isExit(fileName))
{
return !remove(fileName);
}
}
int fileWrite(File* file, const char* buf, int size)
{
return fwrite(buf, size, 1, file);
}
BOOL isExit(const char* fileName)
{
return (_access(fileName, 0) == 0);
}
BOOL fileClose(const File* file)
{
return !fclose(file);
}
FileManager* fileManager()
{
pthread_mutex_lock(&g_mutex);
// C语言堆栈方式
if (NULL == g_fileManager)
{
g_fileManager = (FileManager*)malloc(sizeof(FileManager));
if (NULL != g_fileManager)
{
g_fileManager->exit = isExit;
g_fileManager->mkFile = mkFile;
g_fileManager->write = fileWrite;
g_fileManager->rmFile = rmFile;
g_fileManager->close = fileClose;
}
}
pthread_mutex_unlock(&g_mutex);
return g_fileManager;
}
void releaseFileManager()
{
pthread_mutex_lock(&g_mutex);
if (NULL != g_fileManager)
{
free(g_fileManager);
g_fileManager = NULL;
}
pthread_mutex_unlock(&g_mutex);
}
总结
本介绍了2种懒汉式C语言单例实现,为了简化,本文单例的实现统一采用了 独占锁实现,这种方式的锁性能不是很好,如果你的软件并发性比较大,建议采用读写锁或者双锁机制。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)