Skip to content

Commit 795251a

Browse files
author
Jarry
committed
add singleton for c
1 parent 8a8670b commit 795251a

20 files changed

+397
-89
lines changed

.vscode/settings.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
"iosfwd": "c",
3737
"locale": "c",
3838
"*.tcc": "c",
39-
"system_error": "c"
39+
"system_error": "c",
40+
"__mutex_base": "c",
41+
"mutex": "c"
4042
}
4143
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "func.h"
2+
3+
void eager_singleton_run(EagerSingleton *singleton)
4+
{
5+
printf("\r\n EagerSingleton::run() [name=%s value=%d]", singleton->name, singleton->value);
6+
}
7+
8+
// 直接用static声明struct对象并初始化,相当于实例化类
9+
static EagerSingleton earge_singleton_instance = {
10+
.name = "",
11+
.run = &eager_singleton_run,
12+
.value = 0,
13+
};
14+
15+
// 饿汉模式,全局唯一,系统加载则初始化变量,无并发安全问题,但可能存在浪费
16+
EagerSingleton *get_eager_singleton_instance(char *name)
17+
{
18+
// 如果name为空则更新name
19+
if (strcmp(earge_singleton_instance.name, "") == 0)
20+
{
21+
strcpy(earge_singleton_instance.name, name);
22+
}
23+
return &earge_singleton_instance;
24+
}

singleton-pattern/c/src/func.h

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include <stdio.h>
2+
#include <ctype.h>
3+
#include <stdlib.h>
4+
#include <stdbool.h>
5+
#include <string.h>
6+
7+
// 懒汉模式,不重复实例化,非线程安全
8+
typedef struct LazySingleton LazySingleton;
9+
typedef struct LazySingleton
10+
{
11+
char name[50];
12+
int value;
13+
void (*run)(LazySingleton *);
14+
} LazySingleton;
15+
16+
LazySingleton *get_lazy_singleton_instance();
17+
18+
// 懒汉模式,加锁,线程安全
19+
typedef struct LazySingletonSafe LazySingletonSafe;
20+
typedef struct LazySingletonSafe
21+
{
22+
char name[50];
23+
int value;
24+
void (*run)(LazySingletonSafe *);
25+
} LazySingletonSafe;
26+
LazySingletonSafe *get_lazy_singleton_safe_instance();
27+
28+
// 懒汉模式,加锁,线程安全
29+
typedef struct EagerSingleton EagerSingleton;
30+
typedef struct EagerSingleton
31+
{
32+
char name[50];
33+
int value;
34+
void (*run)(EagerSingleton *);
35+
} EagerSingleton;
36+
EagerSingleton *get_eager_singleton_instance();
37+
38+
// 懒汉模式,加锁,增加volatile
39+
typedef struct LazySingletonVolatile LazySingletonVolatile;
40+
typedef struct LazySingletonVolatile
41+
{
42+
char name[50];
43+
int value;
44+
void (*run)(LazySingletonVolatile *);
45+
} LazySingletonVolatile;
46+
LazySingletonVolatile *get_lazy_singleton_volatile_instance();
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "func.h"
2+
3+
// 静态指针,未被创建并分配内存空间,指向唯一实例
4+
static LazySingleton *lazy_singleton_instance = NULL;
5+
6+
void lazy_singleton_run(LazySingleton *singleton)
7+
{
8+
printf("\r\n LazySingleton::run() [name=%s value=%d]", singleton->name, singleton->value);
9+
}
10+
11+
// 非线程安全懒汉模式,延迟初始化。多个线程同时调用函数时, 可能会被初始化多次,存在线程不安全问题
12+
LazySingleton *get_lazy_singleton_instance(char *name)
13+
{
14+
printf("\r\n get_lazy_singleton_instance() [name=%s]", name);
15+
// 外部的实例,如果不存在则初始化,否则直接返回实例
16+
if (lazy_singleton_instance == NULL)
17+
{
18+
printf("\r\n new instance [name=%s]", name);
19+
lazy_singleton_instance = (LazySingleton *)malloc(sizeof(LazySingleton));
20+
strcpy(lazy_singleton_instance->name, name);
21+
lazy_singleton_instance->run = &lazy_singleton_run;
22+
}
23+
return lazy_singleton_instance;
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include "func.h"
2+
#include <pthread.h>
3+
4+
// 静态指针,未被创建并分配内存空间,指向唯一实例
5+
static LazySingletonVolatile *lazy_singleton_volatile_instance = NULL;
6+
7+
void lazy_singleton_volatile_run(LazySingletonVolatile *singleton)
8+
{
9+
printf("\r\n LazySingletonVolatile::run() [name=%s value=%d]", singleton->name, singleton->value);
10+
}
11+
12+
// 内部私有实例化函数,不公开
13+
static LazySingletonVolatile *new_lazy_singleton_volatile(char *name)
14+
{
15+
LazySingletonVolatile *singleton = (LazySingletonVolatile *)malloc(sizeof(LazySingletonVolatile));
16+
strcpy(singleton->name, name);
17+
singleton->run = &lazy_singleton_volatile_run;
18+
return singleton;
19+
}
20+
21+
static inline void rmb()
22+
{
23+
asm volatile("lfence");
24+
}
25+
26+
static inline void wmb()
27+
{
28+
asm volatile("sfence");
29+
}
30+
31+
// 声明锁
32+
pthread_mutex_t singleton_lock;
33+
34+
// 非线程安全懒汉模式,延迟初始化。多个线程同时调用函数时, 可能会被初始化多次,存在线程不安全问题
35+
LazySingletonVolatile *get_lazy_singleton_volatile_instance(char *name)
36+
{
37+
printf("\r\n get_lazy_singleton_volatile_instance() [name=%s]", name);
38+
if (pthread_mutex_init(&singleton_lock, NULL) != 0)
39+
{
40+
perror("error init mutext:");
41+
}
42+
43+
// 通过加锁和volatile双重机制来防止线程并发导致安全隐患
44+
if (lazy_singleton_volatile_instance == NULL)
45+
{
46+
printf("\r\n new instance [name=%s]", name);
47+
pthread_mutex_lock(&singleton_lock);
48+
rmb();
49+
lazy_singleton_volatile_instance = new_lazy_singleton_volatile(name);
50+
wmb();
51+
pthread_mutex_unlock(&singleton_lock);
52+
}
53+
return lazy_singleton_volatile_instance;
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include "func.h"
2+
#include <pthread.h>
3+
4+
// 静态指针,未被创建并分配内存空间,指向唯一实例
5+
static LazySingletonSafe *lazy_singleton_safe_instance = NULL;
6+
7+
void lazy_singleton_safe_run(LazySingletonSafe *singleton)
8+
{
9+
printf("\r\n LazySingletonSafe::run() [name=%s value=%d]", singleton->name, singleton->value);
10+
}
11+
12+
// 内部私有实例化函数,不公开
13+
static LazySingletonSafe *new_lazy_singleton_safe(char *name)
14+
{
15+
LazySingletonSafe *singleton = (LazySingletonSafe *)malloc(sizeof(LazySingletonSafe));
16+
strcpy(singleton->name, name);
17+
singleton->run = &lazy_singleton_safe_run;
18+
return singleton;
19+
}
20+
21+
// 声明锁
22+
pthread_mutex_t singleton_lock;
23+
24+
// 非线程安全懒汉模式,延迟初始化。多个线程同时调用函数时, 可能会被初始化多次,存在线程不安全问题
25+
LazySingletonSafe *get_lazy_singleton_safe_instance(char *name)
26+
{
27+
printf("\r\n get_lazy_singleton_safe_instance() [name=%s]", name);
28+
if (pthread_mutex_init(&singleton_lock, NULL) != 0)
29+
{
30+
perror("error init mutext:");
31+
}
32+
33+
// 通过加锁来防止线程并发导致的不安全
34+
if (lazy_singleton_safe_instance == NULL)
35+
{
36+
printf("\r\n new instance [name=%s]", name);
37+
pthread_mutex_lock(&singleton_lock);
38+
lazy_singleton_safe_instance = new_lazy_singleton_safe(name);
39+
pthread_mutex_unlock(&singleton_lock);
40+
}
41+
return lazy_singleton_safe_instance;
42+
}

singleton-pattern/c/test/test.c

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include "../src/func.h"
2+
3+
int main(void)
4+
{
5+
printf("test start:\r\n");
6+
/**
7+
* 单例模式就是一个类只创建一个实例,以便节省开销和保证统一
8+
* 对于多线程语言需要注意线程安全和性能之间取得一个平衡
9+
*/
10+
11+
// 懒汉模式,调用函数时实例化
12+
LazySingleton *lazy_singleton1 = get_lazy_singleton_instance("lazySingleton1");
13+
LazySingleton *lazy_singleton2 = get_lazy_singleton_instance("lazySingleton2");
14+
lazy_singleton1->run(lazy_singleton1);
15+
// 实例相同
16+
lazy_singleton2->value = 99;
17+
lazy_singleton2->run(lazy_singleton2);
18+
19+
// 懒汉模式,线程安全
20+
LazySingletonSafe *lazy_singleton_safe1 = get_lazy_singleton_safe_instance("lazySingletonSafe1");
21+
LazySingletonSafe *lazy_singleton_safe2 = get_lazy_singleton_safe_instance("lazySingletonSafe2");
22+
lazy_singleton_safe1->run(lazy_singleton_safe1);
23+
// 实例相同
24+
lazy_singleton_safe2->value = 88;
25+
lazy_singleton_safe2->run(lazy_singleton_safe2);
26+
27+
// 懒汉模式volatile,线程安全
28+
LazySingletonVolatile *lazy_singleton_volatile1 = get_lazy_singleton_volatile_instance("lazySingletonVolatile1");
29+
LazySingletonVolatile *lazy_singleton_volatile2 = get_lazy_singleton_volatile_instance("lazySingletonVolatile2");
30+
lazy_singleton_volatile1->run(lazy_singleton_volatile1);
31+
// 实例相同
32+
lazy_singleton_volatile2->value = 77;
33+
lazy_singleton_volatile2->run(lazy_singleton_volatile2);
34+
35+
// 饿汉模式,已经初始化,可直接使用
36+
EagerSingleton *eager_singleton1 = get_eager_singleton_instance("eagerSingleton1");
37+
EagerSingleton *eager_singleton2 = get_eager_singleton_instance("eagerSingleton2");
38+
eager_singleton1->run(eager_singleton1);
39+
// 实例相同
40+
eager_singleton2->run(eager_singleton2);
41+
}
42+
43+
/**
44+
jarry@jarrys-MacBook-Pro c % gcc test/test.c ./src下*.c
45+
jarry@jarrys-MacBook-Pro c % ./a.out
46+
test start:
47+
48+
proxy_image_constructor() [构建ProxyImage]
49+
ProxyImage::display() [file_name=001.jpg]
50+
real_image_constructor() [构建RealImage]
51+
RealImage::load_from_disk() [file_name=001.jpg]
52+
RealImage::display() [file_name=001.jpg]
53+
ProxyImage::display() [file_name=001.jpg]
54+
RealImage::display() [file_name=001.jpg]%
55+
*/

singleton-pattern/go/src/SingletonInterface.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ var (
2727
syncOnce sync.Once
2828
)
2929

30-
// 条用GetInstance返回SingletonInterface对象
30+
// 利用GetInstance返回SingletonInterface对象
3131
func GetSingletonInterface(name string) SingletonInterface {
3232
// 利用sync.Once来实现一次实例化
3333
syncOnce.Do(func() {
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export class EagerSingleton {
2+
constructor(alias) {
3+
this.alias = alias
4+
}
5+
6+
// 饿汉模式,直接返回已经初始化的实例
7+
static getInstance(alias) {
8+
if (this.instance.alias === undefined || this.instance.alias === '') {
9+
this.instance.alias = alias
10+
}
11+
return this.instance
12+
}
13+
14+
run() {
15+
console.log('EagerSingleton::run()', EagerSingleton.instance.alias)
16+
}
17+
}
18+
19+
// 直接初始化
20+
EagerSingleton.instance = new EagerSingleton('')
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export class LazySingleton {
2+
static instance
3+
constructor(alias) {
4+
this.alias = alias
5+
}
6+
7+
// 懒汉模式,延迟实例化,请求实例时判断,如果已经实例化过就直接返回
8+
// js是单线程语言,无需考虑多线程问题
9+
static getInstance(alias) {
10+
if (this.instance === undefined) {
11+
this.instance = new LazySingleton(alias)
12+
}
13+
return this.instance
14+
}
15+
16+
run() {
17+
console.log('LazySingleton::run()', this.alias)
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
1-
export const SingleObject = (function () {
1+
export const LazySingletonObject = (function () {
22
let instance
3-
4-
// 对象创建方式,如果已经实例化则直接返回对象,类似一个普通Object
3+
// 创建对象,不是class,无需实例化,直接返回对象
54
function createInstance(alias) {
65
if (instance) {
76
return instance
87
}
98
instance = Object.create(null)
109
instance.alias = alias
1110
instance.run = function () {
12-
console.log('SingleObject::()', instance.alias)
11+
console.log('LazySingletonObject::run()', instance.alias)
1312
}
1413
return instance
1514
}
1615

1716
return {
17+
// 通过函数来获得实例,延迟初始化
18+
// 也可以直接执行函数,则立即初始化
1819
getInstance: function (alias) {
1920
if (!instance) {
2021
instance = createInstance(alias)
2122
}
2223
return instance
23-
},
24+
}
2425
}
2526
})()

singleton-pattern/js/src/Singleton.js

-18
This file was deleted.

0 commit comments

Comments
 (0)