网易面试题如何实现一个线程安全的shared_ptr智能指针

Posted 神技圈子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网易面试题如何实现一个线程安全的shared_ptr智能指针相关的知识,希望对你有一定的参考价值。

题目描述

网易一面遇到过这么一个题目,面试官要求自己实现一个线程安全的shared_ptr智能指针。

题目分析

可能很多人只知道shared_ptr是C++11模块库的头文件定义的一个智能指针,即shared_ptr模版。只要将new运算符返回的指针交给shared_ptr这个“管家”,就不必担心在哪里没有delete p了。shared_ptr在被删除的时候会自动执行delete p。通过 shared_ptr 的构造函数,可以让 shared_ptr 对象托管一个 new 运算符返回的指针,写法如下:

        shared_ptr<T> ptr(new T)

此后ptr就像T指针那样用,即ptr就是new动态分配的对象。多个shared_ptr可以共同托管一个指针p,当所有曾经托管p的shared_ptr都解除了对p的托管就会执行delete p。
这个题目拿到手后得搞清楚shared_ptr的原理
1.在其内部,给每个资源都维护了着一份计数,用来记录该份资源被几个对象共享。
2.在对象被销毁时,就说明自己不使用该资源了,对象的引用计数减一。
3.如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源;
4.如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对象就成野指针了。

而且题目既然要求线程安全,就得考虑下面两个问题:
1.智能指针对象中的引用技术是多个对象所共享的,两个线程同时对智能指针进行++或–运算,这个计数原来是1,++了两次可能还是2,这样引用技术就错乱了。会导致资源未释放或者程序崩溃的问题。所以只能指针中引用计数++、–是需要加锁的,也就是说引用计数的操作是线程安全的。
2.智能指针的对象存放在堆上,可能会导致线程安全问题。

线程安全的智能指针代码如下:

#include <utility>
#include <string>
#include <mutex>

using namespace std;

class Counter

public:
   Counter() :
     m_Counter(0)
          

   Counter(const Counter&) = delete;
   Counter& operator=(const Counter&) = delete; 
   ~Counter() 
   void reset() 
       m_Counter = 0;
   
   unsigned int get() const
   
       return m_Counter;
   
   void operator++()
   
       m_Counter++;
   
    
   void operator++(int)
   
       m_Counter++;
   

    void operator--()
   
       m_Counter--;
   
    
   void operator--(int)
   
       m_Counter--;
   
 
   friend ostream& operator<<(ostream& os, const Counter& c)
   
       os << "Counter value: " << c.m_Counter << endl;
       return os;
   
  
private:
   unsigned int m_Counter;      
;

template<typename T>
class Shared_ptr

public:
 explicit Shared_ptr(T *ptr=nullptr):
      m_ptr(ptr),
      m_pCounter(new Counter()),
       m_pMutex(new std::mutex)
   
       if(ptr)
       
           AddRefCount();
       
   
   
   Shared_ptr(Shared_ptr<T>&  sp)
   
       m_ptr = sp.m_ptr;
       m_pCounter = sp.m_pCounter;
       AddRefCount();
   

   Shared_ptr<T>& operator=(const Shared_ptr<T>& sp)
   
       if(m_ptr != sp.m_ptr)
       
           Realse();
           m_ptr = sp.m_ptr;
           m_pCounter = sp.m_pCounter;
           m_pMutex = sp.m_pMutex;
           AddRefCount();
       
   

    T *operator->()
    
        return m_ptr;
    

    T& operator*()
    
        return *m_ptr;
      
    
    T *get()
    
        return m_ptr;
    
        
    unsigned int UseCount()
    
        return m_pCounter->get();
    
    
    ~Shared_ptr()
    
       Realse();    
    

private:
  void AddRefCount()
  
      m_pMutex->lock();
      ++(*m_pCounter);
      m_pMutex->unlock();
  


 void Realse()
 
    bool deleteflag = false;
    m_pMutex->lock();
    --(*m_pCounter);
    if(m_pCounter->get() == 0)
    
        delete m_pCounter;
        delete m_ptr;
        deleteflag = true;
    
    m_pMutex->unlock();
    if(deleteflag == true)
      delete m_pMutex;
     

private:
 T *m_ptr;
 std::mutex *m_pMutex;
 Counter *m_pCounter; 
;

以上是关于网易面试题如何实现一个线程安全的shared_ptr智能指针的主要内容,如果未能解决你的问题,请参考以下文章

网易面试题如何实现一个线程安全的shared_ptr智能指针

网易面试题如何实现一个线程安全的shared_ptr智能指针

java线程(网易大数据面试题)

web前端整套面试题--网易的面试题

Java集合面试题总结

Java面试题-多线程