C语言:单例模式(懒汉式)

C语言:单例模式(懒汉式),第1张

引言

上篇《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语言单例实现,为了简化,本文单例的实现统一采用了 独占锁实现,这种方式的锁性能不是很好,如果你的软件并发性比较大,建议采用读写锁或者双锁机制。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/2889805.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-14
下一篇 2022-09-14

发表评论

登录后才能评论

评论列表(0条)

保存