shared_ptr 智能指针 详解

感觉网上的内容讲解的都不是太说到点子上,陈硕说的还是非常好的。

shared_ptr: 引用计数智能指针。 与auto_ptr的区别是,shared_ptr实现时包含一个引用计数(count-ref)。在一个shared_ptr对象销毁的时候,会将引用计数减一,直到引用计数为0的时候才真正的会销毁其所指向的对象。

int main(){
    shared_ptr<int> sp1(new int(3));
    shared_ptr<int> sp2;
    sp2 = sp1;   //引用计数会增加1,不会导致所有权的转移。
    return 0;    //在函数结束的时候会调用这些局部变量的析构函数,会将引用计数减一,直到引用计数为0.
}

shared_ptr 的内部实现

包括两个部分: T*m_data指向真正的对象; 引用计数的指针(堆上的内存空间的分配)。
(有的人可能会想要采用 static 来实现引用计数,这是不对的)。

VS中 shared_ptr的实现方式,如下图所示:


shared_ptr 线程安全

根据Boost的标准库文档,shared_ptr的线程安全级别 与 内建模型,标准库容器、std::string一样,即:

  • 一个shared_ptr对象可以被多个线程同时读取
  • 两个 shared_ptr 对象可以被 两个线程同时写入,”析构函数“ 算是写操作。
  • 如果两个 线程需要同时写一个 “shared_ptr”对象,那么需要加锁操作。

    请注意,以上是shared_ptr对象本身的线程安全级别,不是它所管理的对象的线程安全级别

以上内容摘自陈硕的博客,讲的很清楚,不过需要时间理解。

  1. 两个线程对同一个shared_ptr对象读肯定是线程安全的。
  2. 两个shared_ptr 对象管理同一个对象,并且分别被两个线程操作: 如果只是操作shared_ptr对象本身,比如说 给这个对象赋值、调用其析构函数、作为复制构造函数的参数等,那么是线程安全的(因为只会操作引用计数,而引用计数是无锁且安全的)。如果两个线程是同时操作 shared_ptr所指向的对象,那么是线程不安全的。 因为对其所管理的对象是没有加锁的。
  3. 如果同一个 shared_ptr 对象 被两个线程同时访问(写),不是线程安全的。 因为 shared_ptr对象包括两个部分 引用计数 与 数据指针。 对这个两个部分的同时访问不是原子操作得。 所以一定不是线程安全得。
  4. shared_ptr对象的引用计数是无锁其安全的,如何实现无锁且安全的呢? 因为引用计数只是一个 integer 变量所以可以用 原子变量 来实现。(特殊的机器指令)

shared_ptr 使用技巧


shared_ptr 的 引用计数含有指向 class T的指针的原因?


引用计数是原子类型的原因?

对于 “为什么引用计数需要原子操作?” 的答案。

我的理解是: 因为 shared_ptr 需要保证 “两个shared_ptr对象可以被两个线程同时写入,析构算是写操作,哪怕这两个shared_ptr 管理同一个对象“ 这个线程安全的级别。

具体来说:

shared_ptr<int> sp1(new int(3));   //线程1,执行 
shared_ptr<int> sp2 = sp1;         //线程2,执行。

sp1 与 sp2 中都有两个指针,并且指向的地方相同。 指向 new int(3) 这片空间, 指向 引用计数的区间。 当线程1 中的 sp1 析构的时候,引用计数此时会减一,这个时候必须是原子操作,才可以保证正确性。 因为需要达到这个级别的线程安全,所以 引用计
数必须是原子类型的。

参考

[1] 陈硕 http://www.cppblog.com/Solstice/archive/2013/01/28/197597.html
[2] 分析与实现http://www.cnblogs.com/gadfly/archive/2010/09/27/1836992.html
[3] http://en.cppreference.com/w/cpp/memory/shared_ptr
[4] shared_ptr 线程安全分析 http://blog.csdn.net/jiangfuqiang/article/details/8292906
[5] 源码剖析 http://my.oschina.net/costaxu/blog/103119
[6] quora https://cppwisdom.quora.com/shared_ptr-is-almost-thread-safe
[7] stackoverflow http://stackoverflow.com/questions/9127816/stdshared-ptr-thread-safety-explained
[8] stackoverflow http://stackoverflow.com/questions/14482830/stdshared-ptr-thread-safety

你可能感兴趣的:(c++,学习之路)