智能指针 shared ptr 的使用方法

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

基于Boost库, C++11 加入了shared_ptrweak_ptr. 它们最早在TR1中就被引入, 但在C++11中, 在Boost的基础上又加入了新的功能.

std::shared_ptr使用引用计数. 每一个shared_ptr的拷贝都指向相同的内存. 在最后一个shared_ptr析构的时候, 内存才会被释放.

 
    
 std::shared_ptr<int> p1(new int(5));std::shared_ptr<int> p2 = p1; // 都指向同一内存. p1.reset(); // 因为p2还在,所以内存没有释放.p2.reset(); // 释放内存, 因为没有shared_ptr指向那块内存了.std::shared_ptr 使用引用计数, 所以有循环计数的问题. 为了打破循环,可以使用std::weak_ptr. 顾名思义, weak_ptr是一个弱引用, 只引用, 不计数. 如果一块内存被shared_ptr和weak_ptr同时引用, 当所有shared_ptr析构了之后,不管还有没有weak_ptr引用该内存, 内存也会被释放. 所以weak_ptr不保证它指向的内存一定是有效的, 在使用之前需要检查.std::shared_ptr<int> p1(new int(5));std::weak_ptr<int> wp1 = p1; // 还是只有p1有所有权. {  std::shared_ptr<int> p2 = wp1.lock(); // p1和p2都有所有权  if(p2) // 使用前需要检查  {     // 使用p2  }} // p2析构了, 现在只有p1有所有权. p1.reset(); // 内存被释放. std::shared_ptr<int> p3 = wp1.lock(); // 因为内存已经被释放了, 所以得到的是空指针.if(p3){  // 不会执行到这.}

shared_ptr的成员方法,user_count()的作用是获得当前对象被引用的次数,reset()的作用是释放指针对对象的引用,将指针设为空。
shared_ptr的线程安全性:
它是这样说的: 

Boost 文档对于 shared_ptr 的线程安全有一段专门的记述,内容如下:
shared_ptr objects offer the same level of thread safety as built-in types. A shared_ptr instance can be "read" (accessed using only const operations) simultaneously by multiple threads. Different shared_ptr instances can be "written to" (accessed using mutable operations such as operator= or reset) simultaneosly by multiple threads (even when these instances are copies, and share the same reference count underneath.)
Any other simultaneous accesses result in undefined behavior.
翻译为中文如下:
shared_ptr 对象提供与内建类型一样的线程安全级别。一个 shared_ptr 实例可以同时被多个线程“读”(仅使用不变操作进行访问)。 不同的 shared_ptr 实例可以同时被多个线程“写入”(使用类似 operator= 或 reset 这样的可变操作进行访问)(即使这些实 例是拷贝,而且共享下层的引用计数)。
任何其它的同时访问的结果会导致未定义行为。”

这几句话比较繁琐,我总结一下它的意思:

1 同一个shared_ptr被多个线程“读”是安全的。

2 同一个shared_ptr被多个线程“写”是不安全的。

3 共享引用计数的不同的shared_ptr被多个线程”写“ 是安全的。

如何印证上面的观点呢?

其实第一点我觉得比较多余。因为在多个线程中读同一个对象,在正常情况下不会有什么问题。

所以问题就是:如何写程序证明同一个shared_ptr被多个线程"写"是不安全的?

我的思路是,在多个线程中同时对一个shared_ptr循环执行两遍swap。 shared_ptr的swap函数的作用就是和另外一个shared_ptr交换引用对象和引用计数,是写操作。执行两遍swap之后, shared_ptr引用的对象的值应该不变。

程序如下:

#include <stdio.h>#include <tr1/memory>#include <pthread.h>using std::tr1::shared_ptr;shared_ptr<int> gp(new int(2000));shared_ptr<int>  CostaSwapSharedPtr1(shared_ptr<int> & p){    shared_ptr<int> p1(p);    shared_ptr<int> p2(new int(1000));    p1.swap(p2);    p2.swap(p1);    return p1;}shared_ptr<int>  CostaSwapSharedPtr2(shared_ptr<int> & p){    shared_ptr<int> p2(new int(1000));    p.swap(p2);    p2.swap(p);    return p;}void* thread_start(void * arg){    int i =0;    for(;i<100000;i++)    {        shared_ptr<int> p= CostaSwapSharedPtr2(gp);        if(*p!=2000)        {            printf("Thread error. *gp=%d \n", *gp);            break;        }    }    printf("Thread quit \n");    return 0;}int main(){    pthread_t thread;    int thread_num = 10, i=0;    pthread_t* threads = new pthread_t[thread_num];    for(;i<thread_num;i++)        pthread_create(&threads[i], 0 , thread_start , &i);    for(i=0;i<thread_num;i++)        pthread_join(threads[i],0);    delete[] threads;    return 0;}

这个程序中我启了10个线程。每个线程调用10万次 CostaSwapSharedPtr2函数。 在CostaSwapSharePtr2函数中,对同一个share_ptr全局变量gp进行两次swap(写操作), 在函数返回之后检查gp的值是否被修改。如果gp值被修改,则证明多线程对同一个share_ptr执行写操作是不安全的。

程序运行的结果如下:


Thread error. *gp=1000 Thread error. *gp=1000 Thread quit Thread quit Thread error. *gp=1000 Thread quit Thread error. *gp=1000 Thread quit Thread error. *gp=1000 Thread quit Thread error. *gp=1000 Thread quit Thread error. *gp=1000 Thread quit Thread error. *gp=1000 Thread quit Thread error. *gp=1000 Thread quit Thread quit

10个线程有9个出错。证明多线程对同一个share_ptr执行写操作是不安全的。
我们在程序中,如果不运行CostaSwapSharedPtr2, 改成运行CostaSwapSharedPtr1呢?
  CostaSwapSharedPtr1和CostaSwapSharedPtr2的区别在于, 它不是直接对全局变量gp进行写操作,而是将gp拷贝出来一份再进行写操作。运行的结果如下:
costa@pepsi:~/test/cpp/shared_ptr$ ./bThread quit Thread quit Thread quit Thread quit Thread quit Thread quit Thread quit Thread quit Thread quit Thread quit


           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

猜你喜欢

转载自blog.csdn.net/hfhhgfv/article/details/83956921
今日推荐