600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 设计模式-单例模式-懒汉式饿汉式探讨

设计模式-单例模式-懒汉式饿汉式探讨

时间:2022-10-21 01:50:13

相关推荐

设计模式-单例模式-懒汉式饿汉式探讨

文章目录

基础概念饿汉式实例懒汉式实例懒汉式实例【互斥锁方式保障线程安全】懒汉式实例【双重检查锁定(Double-Checked Locking)保障线程安全】大型项目中单例模式实用数据库连接池C语言-单例模式实现线程池C语言单例模式-实现日志管理器C语言单例模式-实现高性能配置管理器

基础概念

单例模式是一种常用的设计模式,它可以保证一个类只有一个实例对象,并提供一个全局访问点来访问该实例对象。在实际开发中,常常需要使用单例模式来管理全局资源,例如数据库连接池、线程池等。

单例模式可以分为懒汉式和饿汉式两种实现方式。

懒汉式单例模式是指在第一次使用实例对象时才创建实例对象,而不是在程序启动时就创建实例对象。

懒汉式单例模式的优点是可以节省系统资源,缺点是在多线程环境下可能会出现多个线程同时创建实例对象的问题,需要进行线程安全处理。

饿汉式单例模式是指在程序启动时就创建实例对象(并申请分配内存),而不是在第一次使用实例对象时才创建实例对象。

饿汉式单例模式的优点是可以避免多线程环境下的线程安全问题,缺点是可能会浪费系统资源。

饿汉式实例

#include <stdio.h>#include <stdlib.h>typedef struct {int id;char* name;} Singleton;static Singleton* instance = NULL;/* 只此仅当程序第一次起来,仅跑一次 */void init_instance() {instance = (Singleton*)malloc(sizeof(Singleton));instance->id = 1;instance->name = "Singleton";}Singleton* get_instance() {return instance;}int main() {init_instance();/* 程序一开始,就必须执行。不然,与懒汉式无较大差异 */Singleton* singleton = get_instance();printf("id: %d, name: %s\n", singleton->id, singleton->name);free(instance);return 0;}

懒汉式实例

懒汉式实例【互斥锁方式保障线程安全】

#include <stdio.h>#include <stdlib.h>#include <pthread.h>/* 懒汉单例模式 *//* 互斥锁方式保障线程安全 */typedef struct {int id;char* name;} Singleton;static Singleton* instance = NULL;static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;Singleton* get_instance() {/* 检查实例对象存在性时,获取互斥锁,存在性能开销问题 */pthread_mutex_lock(&mutex);if (instance == NULL) {instance = (Singleton*)malloc(sizeof(Singleton));instance->id = 1;instance->name = "Singleton";}pthread_mutex_unlock(&mutex);return instance;}int main() {Singleton* singleton1 = get_instance();Singleton* singleton2 = get_instance();printf("singleton1: %p, singleton2: %p\n", singleton1, singleton2);return 0;}

懒汉式实例【双重检查锁定(Double-Checked Locking)保障线程安全】

#include <stdio.h>#include <stdlib.h>#include <pthread.h>/* 懒汉单例模式 *//* 双重检查锁定(Double-Checked Locking)保障线程安全 */typedef struct {int id;char* name;} Singleton;static Singleton* instance = NULL;static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;Singleton* get_instance() {/* 优势:* 在第一次检查实例对象是否存在时,不需要获取互斥锁,* 这可以避免每次调用get_instance函数时都需要获取互斥锁的性能问题。* 只有在实例对象不存在时,才获取互斥锁,并再次检查实例对象是否存在,以避免多个线程同时创建实例对象的问题。 *//* 隐患:在使用双重检查锁定方式时,需要保证编译器对静态变量的初始化顺序,否则可能会导致线程安全问题。 */if (instance == NULL) {/* 第一次判空,即第一次检查 */pthread_mutex_lock(&mutex);if (instance == NULL) {/* 第二次判空,即第二次检查 */instance = (Singleton*)malloc(sizeof(Singleton));instance->id = 1;instance->name = "Singleton";}pthread_mutex_unlock(&mutex);}return instance;}int main() {Singleton* singleton1 = get_instance();Singleton* singleton2 = get_instance();printf("singleton1: %p, singleton2: %p\n", singleton1, singleton2);return 0;}

大型项目中单例模式实用

数据库连接池:在大型项目中,通常需要频繁地访问数据库,为了提高数据库访问效率,可以使用数据库连接池来管理数据库连接。数据库连接池可以使用单例模式来实现,保证只有一个数据库连接池实例对象,并提供一个全局访问点来访问该实例对象。

线程池:在大型项目中,通常需要使用多线程来提高系统并发能力,为了避免频繁地创建和销毁线程,可以使用线程池来管理线程。线程池可以使用单例模式来实现,保证只有一个线程池实例对象,并提供一个全局访问点来访问该实例对象。

日志管理器:在大型项目中,通常需要记录系统运行日志,为了方便管理和维护日志,可以使用日志管理器来管理系统日志。日志管理器可以使用单例模式来实现,保证只有一个日志管理器实例对象,并提供一个全局访问点来访问该实例对象。

配置管理器:在大型项目中,通常需要读取和管理系统配置信息,为了方便管理和维护配置信息,可以使用配置管理器来管理系统配置信息。配置管理器可以使用单例模式来实现,保证只有一个配置管理器实例对象,并提供一个全局访问点来访问该实例对象。

数据库连接池

/* C语言实现的简单的数据库连接池的饿汉式单例模式 */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#define MAX_CONNECTIONS 10typedef struct {int id;char* url;char* username;char* password;} Connection;typedef struct {Connection* connections[MAX_CONNECTIONS];int count;pthread_mutex_t lock;} ConnectionPool;static ConnectionPool* instance = NULL;Connection* create_connection(int id, const char* url, const char* username, const char* password) {Connection* conn = (Connection*)malloc(sizeof(Connection));conn->id = id;conn->url = strdup(url);conn->username = strdup(username);conn->password = strdup(password);return conn;}void destroy_connection(Connection* conn) {free(conn->url);free(conn->username);free(conn->password);free(conn);}void init_instance() {instance = (ConnectionPool*)malloc(sizeof(ConnectionPool));instance->count = 0;pthread_mutex_init(&instance->lock, NULL);}ConnectionPool* get_instance() {return instance;}Connection* get_connection() {ConnectionPool* pool = get_instance();pthread_mutex_lock(&pool->lock);Connection* conn = NULL;if (pool->count > 0) {conn = pool->connections[--pool->count];}pthread_mutex_unlock(&pool->lock);return conn;}void release_connection(Connection* conn) {ConnectionPool* pool = get_instance();pthread_mutex_lock(&pool->lock);if (pool->count < MAX_CONNECTIONS) {pool->connections[pool->count++] = conn;} else {destroy_connection(conn);}pthread_mutex_unlock(&pool->lock);}int main() {init_instance();/* 程序一开始,就必须执行。不然,与懒汉式无较大差异 */ConnectionPool* pool = get_instance();for (int i = 0; i < MAX_CONNECTIONS; i++) {Connection* conn = create_connection(i, "localhost", "root", "password");pool->connections[pool->count++] = conn;}Connection* conn1 = get_connection();Connection* conn2 = get_connection();printf("conn1: %p\n", conn1);printf("conn2: %p\n", conn2);release_connection(conn1);release_connection(conn2);return 0;}

C语言-单例模式实现线程池

#include <stdio.h>#include <stdlib.h>#include <pthread.h>#define THREAD_POOL_SIZE 5// 任务结构体typedef struct {void (*task)(void*);void* arg;} Task;// 线程池结构体typedef struct {Task* tasks; // 任务队列int size; // 任务队列大小int head; // 任务队列头指针int tail; // 任务队列尾指针int count; // 任务队列中任务数量pthread_mutex_t lock; // 互斥锁pthread_cond_t not_empty; // 非空条件变量pthread_cond_t not_full; // 非满条件变量int shutdown; // 线程池是否关闭pthread_t* threads; // 工作线程数组int thread_count; // 工作线程数量} ThreadPool;// 线程池单例结构体typedef struct {ThreadPool* pool; // 线程池指针} ThreadPoolSingleton;static ThreadPoolSingleton* instance = NULL; // 线程池单例对象指针// 工作线程函数void* worker(void* arg) {ThreadPool* pool = (ThreadPool*)arg;while (1) {pthread_mutex_lock(&pool->lock);while (pool->count == 0 && !pool->shutdown) {pthread_cond_wait(&pool->not_empty, &pool->lock);}if (pool->count == 0 && pool->shutdown) {pthread_mutex_unlock(&pool->lock);pthread_exit(NULL);}Task task = pool->tasks[pool->head];pool->head = (pool->head + 1) % pool->size;pool->count--;pthread_cond_signal(&pool->not_full);pthread_mutex_unlock(&pool->lock);task.task(task.arg);}return NULL;}// 创建线程池函数ThreadPool* create_thread_pool(int thread_count, int queue_size) {ThreadPool* pool = (ThreadPool*)malloc(sizeof(ThreadPool));pool->tasks = (Task*)malloc(sizeof(Task) * queue_size);pool->size = queue_size;pool->head = 0;pool->tail = 0;pool->count = 0;pthread_mutex_init(&pool->lock, NULL);pthread_cond_init(&pool->not_empty, NULL);pthread_cond_init(&pool->not_full, NULL);pool->shutdown = 0;pool->threads = (pthread_t*)malloc(sizeof(pthread_t) * thread_count);pool->thread_count = thread_count;for (int i = 0; i < thread_count; i++) {pthread_create(&pool->threads[i], NULL, worker, pool);}return pool;}// 销毁线程池函数void destroy_thread_pool(ThreadPool* pool) {pthread_mutex_lock(&pool->lock);pool->shutdown = 1;pthread_mutex_unlock(&pool->lock);pthread_cond_broadcast(&pool->not_empty);for (int i = 0; i < pool->thread_count; i++) {pthread_join(pool->threads[i], NULL);}free(pool->threads);free(pool->tasks);pthread_mutex_destroy(&pool->lock);pthread_cond_destroy(&pool->not_empty);pthread_cond_destroy(&pool->not_full);free(pool);}// 提交任务函数void submit_task(ThreadPool* pool, void (*task)(void*), void* arg) {pthread_mutex_lock(&pool->lock);while (pool->count == pool->size && !pool->shutdown) {pthread_cond_wait(&pool->not_full, &pool->lock);}if (pool->shutdown) {pthread_mutex_unlock(&pool->lock);return;}pool->tasks[pool->tail].task = task;pool->tasks[pool->tail].arg = arg;pool->tail = (pool->tail + 1) % pool->size;pool->count++;pthread_cond_signal(&pool->not_empty);pthread_mutex_unlock(&pool->lock);}// 任务函数void task_func(void* arg) {int* num = (int*)arg;printf("task %d is running\n", *num);free(num);}// 任务包装函数void* task_wrapper(void* arg) {TaskWrapper* wrapper = (TaskWrapper*)arg;submit_task(wrapper->pool, wrapper->task, wrapper->arg);free(wrapper);return NULL;}init_instance() {instance = (ThreadPoolSingleton*)malloc(sizeof(ThreadPoolSingleton));instance->pool = create_thread_pool(THREAD_POOL_SIZE, THREAD_POOL_SIZE);}// 获取线程池单例对象函数ThreadPool* get_thread_pool_instance() {return instance->pool;}int main() {init_instance();/* 程序一开始,就必须执行。不然,与懒汉式无较大差异 */ThreadPool* pool = get_thread_pool_instance(); // 获取线程池单例对象for (int i = 0; i < 10; i++) {int* num = (int*)malloc(sizeof(int));*num = i;TaskWrapper* wrapper = (TaskWrapper*)malloc(sizeof(TaskWrapper));wrapper->pool = poolwrapper->task = task_func;wrapper->arg = num;pthread_t tid;pthread_create(&tid, NULL, task_wrapper, wrapper); // 提交任务}sleep(1); // 等待所有任务执行完毕destroy_thread_pool(pool); // 销毁线程池return 0;}/*该示例代码中,使用了单例模式来创建线程池对象,保证了整个程序中只有一个线程池对象。线程池中包含了任务队列、工作线程数组、互斥锁、条件变量等成员,通过这些成员来实现任务的提交和执行。在主函数中,提交了10个任务,每个任务都是一个简单的打印数字的函数,最后等待所有任务执行完毕后销毁线程池。*/

C语言单例模式-实现日志管理器

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <pthread.h>// 日志级别枚举typedef enum {LOG_LEVEL_DEBUG,LOG_LEVEL_INFO,LOG_LEVEL_WARN,LOG_LEVEL_ERROR,LOG_LEVEL_FATAL} LogLevel;// 日志管理器结构体typedef struct {FILE* file; // 日志文件指针LogLevel level; // 日志级别pthread_mutex_t lock; // 互斥锁} LogManager;// 日志管理器单例结构体typedef struct {LogManager* manager; // 日志管理器指针} LogManagerSingleton;static LogManagerSingleton* instance = NULL; // 日志管理器单例对象指针// 获取当前时间字符串函数void get_current_time_string(char* buffer, size_t size) {time_t now = time(NULL);struct tm* tm = localtime(&now);strftime(buffer, size, "%Y-%m-%d %H:%M:%S", tm);}// 写日志函数void write_log(LogLevel level, const char* message) {LogManager* manager = instance->manager;if (level < manager->level) {return;}char time_str[20];get_current_time_string(time_str, sizeof(time_str));pthread_mutex_lock(&manager->lock);fprintf(manager->file, "[%s] ", time_str);switch (level) {case LOG_LEVEL_DEBUG:fprintf(manager->file, "[DEBUG] ");break;case LOG_LEVEL_INFO:fprintf(manager->file, "[INFO] ");break;case LOG_LEVEL_WARN:fprintf(manager->file, "[WARN] ");break;case LOG_LEVEL_ERROR:fprintf(manager->file, "[ERROR] ");break;case LOG_LEVEL_FATAL:fprintf(manager->file, "[FATAL] ");break;}fprintf(manager->file, "%s\n", message);fflush(manager->file);// 将写缓存区立即写入磁盘。pthread_mutex_unlock(&manager->lock);}// 设置日志级别函数void set_log_level(LogLevel level) {instance->manager->level = level;}init_instance() {instance = (LogManagerSingleton*)malloc(sizeof(LogManagerSingleton));instance->manager = (LogManager*)malloc(sizeof(LogManager));instance->manager->file = fopen("log.txt", "a");instance->manager->level = LOG_LEVEL_INFO;// 日志默认级别INFOpthread_mutex_init(&instance->manager->lock, NULL);}// 获取日志管理器单例对象函数LogManager* get_log_manager_instance() {return instance->manager;}int main() {init_instance();/* 程序一开始,就必须执行。不然,与懒汉式无较大差异。 */LogManager* manager = get_log_manager_instance(); // 获取日志管理器单例对象set_log_level(LOG_LEVEL_DEBUG); // 设置日志级别为DEBUGwrite_log(LOG_LEVEL_DEBUG, "debug message"); // 写DEBUG级别日志write_log(LOG_LEVEL_INFO, "info message"); // 写INFO级别日志write_log(LOG_LEVEL_WARN, "warn message"); // 写WARN级别日志write_log(LOG_LEVEL_ERROR, "error message"); // 写ERROR级别日志write_log(LOG_LEVEL_FATAL, "fatal message"); // 写FATAL级别日志fclose(manager->file); // 关闭日志文件pthread_mutex_destroy(&manager->lock); // 销毁互斥锁free(manager); // 释放日志管理器内存free(instance); // 释放日志管理器单例对象内存return 0;}/*该示例代码中,使用了单例模式来创建日志管理器对象,保证了整个程序中只有一个日志管理器对象。日志管理器中包含了日志文件指针、日志级别、互斥锁等成员,通过这些成员来实现日志的写入和级别控制。在主函数中,设置了日志级别为DEBUG,并写入了5条不同级别的日志,最后关闭日志文件、销毁互斥锁、释放内存。*/

C语言单例模式-实现高性能配置管理器

代码中,使用了单例模式来创建配置管理器对象,保证了整个程序中只有一个配置管理器对象。配置管理器中包含了配置项数组、配置项数量、互斥锁等成员,通过这些成员来实现配置文件的读取和配置项的获取。在主函数中,获取了一个配置项的值,并打印出来,最后销毁互斥锁、释放内存。

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#define MAX_CONFIG_SIZE 1024// 配置项结构体typedef struct {char* key; // 配置项键char* value; // 配置项值} ConfigItem;// 配置管理器结构体typedef struct {ConfigItem* items; // 配置项数组int count; // 配置项数量pthread_mutex_t lock; // 互斥锁} ConfigManager;// 配置管理器单例结构体typedef struct {ConfigManager* manager; // 配置管理器指针} ConfigManagerSingleton;static ConfigManagerSingleton* instance = NULL; // 配置管理器单例对象指针// 读取配置文件函数void read_config_file(const char* filename) {ConfigManager* manager = instance->manager;FILE* file = fopen(filename, "r");if (file == NULL) {return;}char line[MAX_CONFIG_SIZE];while (fgets(line, sizeof(line), file) != NULL) {char* key = strtok(line, "=");char* value = strtok(NULL, "\n");if (key != NULL && value != NULL) {ConfigItem item;item.key = strdup(key);item.value = strdup(value);pthread_mutex_lock(&manager->lock);manager->items[manager->count++] = item;pthread_mutex_unlock(&manager->lock);}}fclose(file);}// 获取配置项值函数const char* get_config_value(const char* key) {ConfigManager* manager = instance->manager;for (int i = 0; i < manager->count; i++) {if (strcmp(manager->items[i].key, key) == 0) {return manager->items[i].value;}}return NULL;}// 获取配置管理器单例对象函数ConfigManager* get_config_manager_instance() {if (instance == NULL) {instance = (ConfigManagerSingleton*)malloc(sizeof(ConfigManagerSingleton));instance->manager = (ConfigManager*)malloc(sizeof(ConfigManager));instance->manager->items = (ConfigItem*)malloc(sizeof(ConfigItem) * MAX_CONFIG_SIZE);instance->manager->count = 0;pthread_mutex_init(&instance->manager->lock, NULL);read_config_file("config.txt");}return instance->manager;}int main() {ConfigManager* manager = get_config_manager_instance(); // 获取配置管理器单例对象const char* value = get_config_value("key1"); // 获取配置项值if (value != NULL) {printf("key1=%s\n", value);}pthread_mutex_destroy(&manager->lock); // 销毁互斥锁free(manager->items); // 释放配置项数组内存free(manager); // 释放配置管理器内存free(instance); // 释放配置管理器单例对象内存return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。