2020年3月16日 下午4:41
总结1:
- 在多线程下什么场景进行对象操作不安全?
- 线程可以释放:不同线程之间,不知道自己所指的内存对应的对象是否还活着,有可能被其中一个线程释放了,那其他线程此时在调用就报错了
- 线程不可以释放:要不就是在堆中,所有线程都别释放,这样显然不成
- 这两种方法都不好!
- 为什么smart_ptr可以实现对多线程下对象生命周期的管理?
- 我们从下面的代码中在单线程下的测试输出可以看出,smart_ptr的本质是对象资源的管理,将对象析构的权利给予到第三方的smart_ptr。
- 对象内存的资源释放与作用域{},所在的线程都是无关的,至于引用计数值=0相关
- 当smart_ptr对象超出自己的作用域{}之后,即使自己被析构了,但是smart_ptr指向的对象引用计数值!=0,那么这个对象还是没有被析构的
- 析构所在的线程不一定是资源对象诞生的线程P20
- smart_ptr完成的是对资源对象的引用计数,计数的能力是不受线程并发的影响的!所以,smart_ptr可以直接用到多线程场景下。
- 为什么对象中的mutex不能解决?
- 编写线程安全的类不是难事,使用同步原语(eg:mutex)来保护内部状态,但是对象的生死不能由对象拥有的mutex进行保护。
- 析构函数会将对象中的mutex成员变量进行销毁
总结2
- smart_ptr是一种类似于解决单点登录的”设计“问题,smart_ptr的本质是对象资源的管理,将对象析构的权利给予到第三方的smart_ptr,这样大家都别抢,我smart_ptr保证对每一位用户负责。
- smart_ptr核心目的有2:
- 在域外能够自动析构对象,做到RAII
- 共享计数:
- 也就说这个计数能是每个smart_ptr对象有各自的计数,实现的方式就像是单点登录中redis的作用,在多个tomcat之间共享
- 一个smart_ptr加、减,其他的相同指向的smart_ptr都可以看到
- 代码实现的关键:
smart_ptr<circle> ptr1(new circle());这里面new circle()产生的对象是分配在堆上的,不受main()函数作用域限制,需要我们手动进行释放- smart_ptr.h中class smart_ptr的实现的关键在于:
- 多种构造函数:绿色
- 指针常用运算符的重载:红色
- shared_count是一个指针类型:黄色

代码:
- 这份代码包含了shard_ptr 和 unique_ptr
- main.cpp*
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
int main()
{
// 唯一的一个对象实体new circle()
smart_ptr<circle> ptr1(new circle());
printf("use count of ptr1 is %ld\n", ptr1.use_count());
smart_ptr<shape> ptr2;
printf("use count of ptr2 was %ld\n", ptr2.use_count());
// 赋值运算符重载
ptr2 = ptr1;
printf("use count of ptr2 is now %ld\n", ptr2.use_count());
if (ptr1) {
puts("ptr1 is not empty");
}
// 测试smart_ptr的强制类型转换
smart_ptr<circle> ptr3 = dynamic_pointer_cast<circle>(ptr2);
printf("use count of ptr3 is %ld\n", ptr3.use_count());
// 移动构造函数调用
smart_ptr<shape> ptr4 = std::move(ptr2);
printf("use count of ptr4 is %ld\n", ptr4.use_count());
printf("use count of ptr2 is now %ld\n", ptr2.use_count());
// 指向相同对象的smart_ptr有相同的conut
printf("use count of ptr1 is now %ld\n", ptr1.use_count());
printf("use count of ptr2 is now %ld\n", ptr2.use_count());// 由于我们使用了移动语义,这里就成0了
printf("use count of ptr3 is now %ld\n", ptr3.use_count());
/** 输出
circle()
use count of ptr1 is 1
use count of ptr2 was 0
use count of ptr2 is now 2
ptr1 is not empty
use count of ptr3 is 3
use count of ptr4 is 3
use count of ptr2 is now 0
use count of ptr1 is now 3
use count of ptr2 is now 0
use count of ptr3 is now 3
~circle()
* ***/
}
shape.h
1 |
|
smart_ptr.h
1 |
|