引言

上篇《C语言:单例模式(饿汉式)》,我们介绍了单例的饿汉式实现,本文将向大家继续介绍单例的懒汉式实现方式。

懒汉式

懒汉式,本意就是说这种实现像懒汉一样,不到紧要关头绝不创建对象。常用的有两种实现方式:第一种方式是把对象声明为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 <pthread.h>
#include <io.h>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 <stdio.h>
#include <stdlib.h>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 <pthread.h>
#include <io.h>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语言单例实现,为了简化,本文单例的实现统一采用了 独占锁实现,这种方式的锁性能不是很好,如果你的软件并发性比较大,建议采用读写锁或者双锁机制。

C语言:单例模式(懒汉式)相关推荐

  1. 有关单例模式懒汉式安全的问题(全)

    有关单例模式懒汉式安全的问题(全) 单例模式有两种一种是懒汉式,一种是饿汉式,他们有什么区别呢? 他们建立单例对象的时间不同,懒汉式的特点是延迟加载,当你用到的时候才去建立对象, 还有懒汉式多线程是不 ...

  2. 单例模式-懒汉式和恶汉式

    单例 /*** @author jiyu* @date 2020/12/09 9:09* @description 单例模式 懒汉式 在第一次调用的时候实例化*/ public class Singl ...

  3. 单例模式 懒汉式与恶汉式

    单例模式 懒汉式与恶汉式_打不倒我的,会让我更坚强_百度空间 http://hi.baidu.com/5053738058/item/0853dde084d23fe5fa42ba18 转载于:http ...

  4. 单例模式懒汉式和饿汉式区别

    单例模式懒汉式和饿汉式区别 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单 ...

  5. 单例模式懒汉式和饿汉式的区别

    文章目录 一.单例模式 二.懒汉式和饿汉式 一.单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最 ...

  6. Java多线程:多线程同步安全问题的 “三“ 种处理方式 ||多线程 ”死锁“ 的避免 || 单例模式”懒汉式“的线程同步安全问题

    Java多线程:多线程同步安全问题的 "三" 种处理方式 ||多线程 "死锁" 的避免 || 单例模式"懒汉式"的线程同步安全问题 每博一文 ...

  7. Java单例模式--------懒汉式和饿汉式

    Java单例模式--------懒汉式和饿汉式 单件模式用途: 单件模式属于工厂模式的特例,只是它不需要输入参数并且始终返回同一对象的引用. 单件模式能够保证某一类型对象在系统中的唯一性,即某类在系统 ...

  8. Spring框架学习day_01: 框架配置方式/ 管理对象的作用域/ 生命周期/ 组件扫描/ 单例模式:“懒汉式“,“饿汉式“

    1. Spring框架的作用 Spring框架的主要作用是创建对象和管理对象. 创建对象:类似于User user = new User(); 管理对象:随时可以通过Spring框架获取对象,甚至Sp ...

  9. 单例模式懒汉式(线程安全写法)

    package com.atguigu.java1;/*** 使用同步机制将单例模式中的懒汉式改写为线程安全的** @author shkstart* @create 2019-02-15 下午 2: ...

  10. java 恶汉和懒汉_Java单例模式-懒汉式、恶汉式与线程安全问题

    Java的单例模式常见的分为懒汉式.饿汉式.静态内部类.枚举 通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数额控制并节约系统资源. 饿汉式: public cl ...

最新文章

  1. 6 redhat 查看rtc时间_甜甜老师的DB Fun圈第2讲:GaussDB 100 OLTP 单机在RHEL7.6上的安装...
  2. Struts2中五个重要的常量
  3. 数据结构之稀疏数组 - SparseArray
  4. 注入技术--消息hook注入
  5. Juniper NetScreen 基于源NAT转换
  6. 机器人专用符文_英雄联盟【LOL】手游部分英雄天赋符文和出装推荐
  7. C语言中声明和定义的区别
  8. 自己写的一段预测双色球号码的Java代码
  9. GdiPlus[30]: IGPPen: 线帽
  10. 干货|基于 Spring Cloud 的微服务落地
  11. js (jQuery)分组数据
  12. 未知宽高元素的水平垂直居中
  13. 联想小新增加固态硬盘后安装不了系统_4千价位也能面面俱到?小新Air14 2020锐龙版体验测试...
  14. AD PCB板子长度宽度 PCB板子尺寸大小信息
  15. php版本与vc运行库
  16. 云信duilib之菜单
  17. Ticket Lock的Relaxed Atomics优化
  18. 计算机cpu风扇不转怎么办,电脑cpu风扇不转是怎么回事
  19. 怎样做一个软件注册程序
  20. BGP邻居路由条目数超限

热门文章

  1. mysql按照时间自动创建分区表_mysql 表分区、按时间函数分区、删除分区、自动添加表分区...
  2. 基于SpringBoot的API网关实现
  3. 所有子字符串美丽值之和
  4. myelicpes2019初次使用设置_PES2019技巧(键盘操作,个人经验)
  5. 使用pymupdf开发pdf查看编辑器
  6. 设计精美餐厅菜单的10多个技巧
  7. 2021最新PHP/Redis 高级面试题
  8. IOS 申请证书 出现用户名密码错误的解决
  9. JS阻止浏览器滚动事件
  10. CSGO社区服务器搭建架设服务器配置以及环境准备