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语言和设计模式(之单件模式)