单例模式

​ 单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<iostream>
using namespace std;

//实现单例步骤
//1.构造函数私有化
//2.增加静态私有的当前类的指针变量
//3.提供静态对外公共接口,获得单例对象

//单例 分为懒汉式 饿汉式

//1.懒汉式(需要的时候才会创建)
class Single_lazy {
private:
//静态锁,是由于静态函数只能访问静态成员
static pthread_mutex_t lock;

//私有化构造函数
Single_lazy() {
pthread_mutex_init(&lock, NULL);
}

//当前类的私有静态指针变量指向唯一实例
static Single_lazy *p;

~Single_lazy(){}

public:
//公有静态方法获取实例
static Single_lazy* getInstance();
};

pthread_mutex_t single::lock;

//类外初始化
Single_lazy* Single_lazy::p = NULL;
Single_lazy* Single_lazy::getInstance(){
if(p == NULL){
pthread_mutex_lock(&lock);
if(p == NULL){
p = new Single_lazy;
}
pthread_mutex_unlock(&lock);
}
return p;
}

//为什么要用双检测,只检测一次不行吗?
//如果只检测一次,在每次调用获取实例的方法时,都需要加锁,
//这将严重影响程序性能。双层检测可以有效避免这种情况,
//仅在第一次创建单例的时候加锁,
//其他时候都不再符合NULL==p的情况,
//直接返回已创建好的实例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main

import (
"fmt"
"sync"
)

//实现单例步骤
//1.构造函数私有化
//2.增加静态私有的当前类的指针变量
//3.提供静态对外公共接口,获得单例对象

//单例 分为懒汉式 饿汉式

//1.懒汉式(需要的时候才会创建)
type SingleLazy struct {
}

var (
instanceLazy *SingleLazy
onceLazy sync.Once
)

//公有静态方法获取实例
func GetInstanceLazy() *SingleLazy {
onceLazy.Do(func() {
instanceLazy = &SingleLazy{}
})
return instanceLazy
}

//sync.Once内部使用了双重检查锁定模式,
//保证了线程安全且只初始化一次。
//Do方法只会在第一次调用时执行传入的函数,
//之后的调用都会直接返回,不会重复执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//局部静态变量之线程安全懒汉模式
class Single_lazy{
private:
Single_lazy() {}
~Single_lazy() {}

public:
static Single_lazy* getInstance();
}

Single_lazy* Single_lazy::getInstance(){
static Single_lazy obj;
return &obj;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//局部静态变量之线程安全懒汉模式
type SingleLazyStatic struct {
}

var (
instanceLazyStatic *SingleLazyStatic
onceLazyStatic sync.Once
)

func GetInstanceLazyStatic() *SingleLazyStatic {
onceLazyStatic.Do(func() {
instanceLazyStatic = &SingleLazyStatic{}
})
return instanceLazyStatic
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//2.饿汉式
class Single_hungry {
private:
//当前类的私有静态指针变量指向唯一实例
static Single_hungry* p;

//私有化构造函数
Single_hungry(){}
~Single_hungry(){}

public:
static Single_hungry* getInstance();
};

//类外初始化
Single_hungry* Single_hungry::p = new Single_hungry;
Single_hungry* Single_hungry::getInstance(){
return p;
}

//饿汉模式不需要用锁,就可以实现线程安全。
//原因在于,在程序运行时就定义了对象,并对其初始化。
//之后,不管哪个线程调用成员函数getinstance(),
//都只不过是返回一个对象的指针而已。所以是线程安全的,
//不需要在获取实例的成员函数中加锁。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//2.饿汉式
type SingleHungry struct {
}

var instanceHungry *SingleHungry = &SingleHungry{}

func GetInstanceHungry() *SingleHungry {
return instanceHungry
}

//饿汉模式不需要用锁,就可以实现线程安全。
//原因在于,在程序运行时就定义了对象,并对其初始化。
//之后,不管哪个线程调用成员函数getinstance(),
//都只不过是返回一个对象的指针而已。所以是线程安全的,
//不需要在获取实例的成员函数中加锁。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void test01() {
Single_lazy* p1 = Single_lazy::getInstance();
Single_lazy* p2 = Single_lazy::getInstance();
if (p1 == p2) {
cout << "两个指针指向同一块内存空间,是单例!" << endl;
}
else {
cout << "不是单例模式!" << endl;
}

Single_hungry* p3 = Single_hungry::getInstance();
Single_hungry* p4 = Single_hungry::getInstance();
if (p3 == p4) {
cout << "两个指针指向同一块内存空间,是单例!" << endl;
}
else {
cout << "不是单例模式!" << endl;
}
}

int main() {

test();
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func test01() {
p1 := GetInstanceLazy()
p2 := GetInstanceLazy()
if p1 == p2 {
fmt.Println("两个指针指向同一块内存空间,是单例!")
} else {
fmt.Println("不是单例模式!")
}

p3 := GetInstanceHungry()
p4 := GetInstanceHungry()
if p3 == p4 {
fmt.Println("两个指针指向同一块内存空间,是单例!")
} else {
fmt.Println("不是单例模式!")
}
}

func main() {
test01()
}
-------------本文结束 感谢阅读-------------
0%