单例模式(C语言)
C语言的设计模式(单例模式)
单例模式(Singleton Pattern)是一种设计模式,目的是确保一个类只有一个实例
,并提供一个全局访问点
。
#include "stdio.h"
#include "stdlib.h"// 定义一个结构体来存储串口配置数据
typedef struct
{int baudRate;int dataBits;int stopBits;} SerialConfig;// 声明一个静态全局变量用于存储单实例
static SerialConfig *serialInstance = NULL;// 获取单实例对象的函数
SerialConfig *getSerialConfigInstance()
{if (serialInstance == NULL){// 如果实例不存在,则创建一个新实例并初始化数据serialInstance = (SerialConfig *)malloc(sizeof(SerialConfig));serialInstance->baudRate = 115200; // 初始化数据serialInstance->dataBits = 8; // 初始化数据serialInstance->stopBits = 1; // 初始化数据}return serialInstance;
}// 释放单实例对象的函数
void freeSerialConfigInstance()
{if (serialInstance != NULL){free(serialInstance);serialInstance = NULL;}
}int main()
{// 获取串口配置的单实例SerialConfig *usart1Config = getSerialConfigInstance();SerialConfig *usart2Config = getSerialConfigInstance();// 打印串口配置的参数printf("Baud Rate: %d\n", usart1Config->baudRate);printf("Data Bits: %d\n", usart1Config->dataBits);printf("Stop Bits: %d\n", usart1Config->stopBits);printf("Baud Rate: %d\n", usart2Config->baudRate);printf("Data Bits: %d\n", usart2Config->dataBits);printf("Stop Bits: %d\n", usart2Config->stopBits);// 释放单实例对象freeSerialConfigInstance();return 0;
}
以上是一个比较具体的例子。但是在多线程中使用的话会出现一些问题:
- 线程安全性:如果在多线程中使用,可能会创建多个实例。因为如果两个线程几乎同时调用
getSerialConfigInstance
函数时,他们会同时发现serialInstance
为NULL
,从而各自创建一个新的实例,这样就违背了单例模式的初衷,导致多个实例的存在。此时需要引入同步机制,比如互斥锁(mutex)
来确保线程的安全。
#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"// 定义一个结构体来存储串口配置数据
typedef struct
{int baudRate;int dataBits;int stopBits;} SerialConfig;// 声明一个静态全局变量用于存储单实例
static SerialConfig *serialInstance = NULL;
// 创建互斥锁
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;// 获取单实例对象的函数
SerialConfig *getSerialConfigInstance()
{// 上锁pthread_mutex_lock(&mutex);if (serialInstance == NULL){// 如果实例不存在,则创建一个新实例并初始化数据serialInstance = (SerialConfig *)malloc(sizeof(SerialConfig));serialInstance->baudRate = 115200; // 初始化数据serialInstance->dataBits = 8; // 初始化数据serialInstance->stopBits = 1; // 初始化数据}// 解锁pthread_mutex_unlock(&mutex);return serialInstance;
}// 释放单实例对象的函数
void freeSerialConfigInstance()
{// 上锁pthread_mutex_lock(&mutex);if (serialInstance != NULL){free(serialInstance);serialInstance = NULL;}// 解锁pthread_mutex_unlock(&mutex);
}int main()
{// 获取串口配置的单实例SerialConfig *usart1Config = getSerialConfigInstance();SerialConfig *usart2Config = getSerialConfigInstance();// 打印串口配置的参数printf("Baud Rate: %d\n", usart1Config->baudRate);printf("Data Bits: %d\n", usart1Config->dataBits);printf("Stop Bits: %d\n", usart1Config->stopBits);printf("Baud Rate: %d\n", usart2Config->baudRate);printf("Data Bits: %d\n", usart2Config->dataBits);printf("Stop Bits: %d\n", usart2Config->stopBits);// 释放单实例对象freeSerialConfigInstance();return 0;
}
在这段代码中,pthread_mutex_lock
和 pthread_mutex_unlock
确保了在创建实例的过程中只有一个线程能够访问临界区,从而避免了多个实例的创建。
文章参考:C语言和设计模式(之单件模式)
相关文章:
单例模式(C语言)
C语言的设计模式(单例模式) 单例模式(Singleton Pattern)是一种设计模式,目的是确保一个类只有一个实例,并提供一个全局访问点。 #include "stdio.h" #include "stdlib.h"// 定义一个…...
js前端格式化日期函数
开发需求 在前端中我们通常使用new Date()函数获取到的日期时间是下面这种样子:Thu Jun 06 2024 17:29:11 GMT0800 (中国标准时间),我们想要把它转换成常见的指定格式,比如 年-月-日 时:分:秒年/月/日 时:分:秒年-月-日年/月/日 所以就封装…...

五个超实用的 ChatGPT-4o 提示词
GPT-4o 是 OpenAI 最近推出的最新人工智能模型,不仅具备大语言模型的能力,而且拥有多模态模型的看、读、说等能力,而且速度比 GPT-4 更快。下面我们就来介绍几个超实用的 GPT-4o 提示词,帮助大家更好地了解 GPT-4o 的功能和应用场…...

基于51单片机多功能防盗报警proteus仿真( proteus仿真+程序+设计报告+原理图+讲解视频)
基于51单片机多功能防盗报警系统 1. 主要功能:2. 讲解视频:3. 仿真4. 程序代码5. 设计报告6. 原理图7. 设计资料内容清单&&下载链接 基于51单片机多功能防盗报警系统( proteus仿真程序设计报告原理图讲解视频) 仿真图proteus8.9及以上…...
gitee和github的协同
假设gitee上zhaodezan有一个开发库,但是从andeyeluguo上拉取最新的(从github上同步过来最新的) git remote add dbgpt_in_gitee https://gitee.com/andeyeluguo/DB-GPT.git remote -v git pull --rebase dbgpt_in_gitee main 有冲突可能需要…...

压力测试-性能指标-Jmeter使用-压力测试报告
文章目录 1.压测目的2.性能指标3.Jmeter3.1Jmeter使用3.1.1 运行Jmeter3.1.2 添加线程组3.1.3设置HTTP请求3.1.4 设置监视器 3.2 查看Jmeter压测结果3.2.1 查看结果树3.2.2 查看汇总报告3.2.3 查看聚合报告3.2.4 查看汇总图 1.压测目的 内存泄漏:OOM,重…...
通过Slf4j中的MDC实现在日志中添加用户IP功能
一、slf4j中MDC是什么 slf4j除了trace、debug、info、warn、error这几个日志接口外,还可以配合MDC将数据写入日志。换句话说MDC也是用来记录日志的,但它的使用方式与使用日志接口不同。 在使用日志接口时我们一般这么做 log.debug("log debug"…...
代码随想录算法训练营第四十九天| 139.单词拆分、背包问题总结
139.单词拆分 题目链接:139.单词拆分 文档讲解:代码随想录/单词拆分 视频讲解:视频讲解-单词拆分 状态:已完成(0遍) 解题过程 这几天博主忙着面试和入职,一晃已经周四了,这个礼拜…...

STM32F103VE和STM32F407VE的引脚布局
STM32F103VE vs STM32F407VE 引脚对比表 引脚 STM32F103VE STM32F407VE 备注 1 VSS VSS 地 2 VDD VDD 电源 3 VSSA VSSA 模拟地 4 VDDA VDDA 模拟电源 5 OSC_IN OSC_IN 外部时钟输入 6 OSC_OUT OSC_OUT 外部时钟输出 7 NRST NRST 复位 8 PC13 (GPIO) PC13 (GPIO) GPIO 9 PC14 (…...
搜维尔科技:使用 Xsens 动作捕捉技术创建栩栩如生的动画
使用Xsens 动作捕捉技术创建栩栩如生的动画 搜维尔科技:使用 Xsens 动作捕捉技术创建栩栩如生的动画...
鸿蒙开发 一 (三)、ArkTS开发实战上
ArkTS 从 TypeScript 优化而来, 但有些用法又不太一样, 在开发中, 经常会出现一些报错提示,下面我们也汇总一些常见错误,捡一些常见的整理一下 Promise 的用法: //TypeScript 写法:private load…...
TensorRT教程(1)初探TensorRT
1. TensorRT简要介绍 TensorRT(NVIDIA TensorRT)是 NVIDIA 开发的一个用于深度学习推理的高性能推理引擎。它可以针对 NVIDIA GPU 进行高效的深度学习推理加速,提供了许多优化技术,使得推理速度更快,并且可以在生产环境…...

多表连接查询和子查询
一、连接查询 连接查询是SQL语言最强大的功能之一,它可以执行查询时动态的将表连接起来,然后从中查询数据。 1.1、连接两表的方法 在SQL中连接两表可以有两种方法,一种是无连接规则连接,另一种是有连接规则连接。 无连接规则连…...

数据挖掘与机器学习——聚类算法
目录 无监督学习 聚类算法 概念: 功能: 应用场景: 评判标准: 划分聚类: K-means聚类 逻辑实现: 聚类方式 问题: 解决: 可能存在的问题: 1.初始值对K-means聚…...

QT快速下载
去QT官网之后,如下图所示 比如要下载qt-opensource-windows-x86-5.14.2.exe,进入5.14对应的文件夹,找到对应的版本 点击Details, 下载对应的种子,然后通过迅雷下载 个人实测,家庭网络平均18M的速率...

最短路问题
最短路问题是图论里非常经典的一个考点 接下来着重讲述五种求最短路的算法:朴素版dijkstra算法、堆优化版的dijkstra算法、bellman-ford算法、spfa算法、floyd算法 总体思维导图: 总体思路: 最短路分为两大类 { 在以下给出的时间复杂度中n…...
spark MLlib 中的分类模型
理解这些机器学习模型的数学原理需要一定的数学基础,下面我将简要介绍每个模型的数学原理,并附上相关的数学公式。 1. LinearSVC(线性支持向量机) 数学原理: 线性支持向量机的目标是找到一个超平面,最大化…...
24上半年报考人数“不增反降”?备考下半年软考的难了......
近日,工信教考发布了一篇《2024年上半年计算机软件资格考试顺利举行》的文章,公布了2024年上半年软考报考人数共计52.77万人,其中,初级资格5.12万人、中级资格24.37万人、高级资格23.28万人。 软考高级占总报名人数的44%…...

初出茅庐的小李博客之使用立创开发板(ESP32)连接到EMQX Platform【MQTT TLS/SSL 端口连接】
介绍 手上有一块立创开发板,本着不吃灰的原则把它用起来,今天就来用它来连接上自己部署的MQTT服务器进行数据通信。 硬件:立创开发板 开发环境:Arduino IDE Win11 MQTT 平台:EMQX Platform 立创开发板介绍࿱…...
js平滑滚动元素使其可见
直接上重点: let xpath "//*/div[idxxx]"; document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.scrollIntoView({ behavior: "smooth"})这段代码是JavaScript中使用XPath查询文档并执行平…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...