其他分享
首页 > 其他分享> > c-引用计数类和多线程

c-引用计数类和多线程

作者:互联网

我是多线程编程的新手,对此我仍然感到困惑.

以下是我的参考计数课程:

class Rbuffer
{
  private:
    char *m_pnData;
    volatile unsigned int mRefCount;

  public:
     Rbuffer(int nLength) : mRefCount(0)
    {
    m_pnData = new char[nLength]; 
    }
   ~Rbuffer(){
    delete[] m_pnData;
    }

   void decRef() {
     if(InterlockedDecrement(&mRefCount)==0){
               delete (Rbuffer *)this;
           }
    }

  void incRef() {
        InterlockedIncrement(&mRefCount);
    } 

}; 

它是完全线程安全的吗?您能否排除这种情况:

ThreadA                                 ThreadB
PointerToRBuffer->incRef();//mRefCount 1
switch->  
                                        PointerToRBuffer->incRef();//mRefCount 2
                                          <-switch
PointerToRBuffer->decRef();           
InterlockedDecrement(&mRefCount)//mRefCount 1 
switch->                                
                                        PointerToRBuffer->decRef();//mRefCount 0!
                                        InterlockedDecrement(&mRefCount);
                                        if (0==0)
                                        delete (Rbuffer *)this; 
                                            <-switch
if (0==0) 
//deleting object, that doesn't exist 
delete (Rbuffer *)this;
//CRASH                               

崩溃的原因可能只是(InterlockedDecrement(& mRefCount))部分是原子的,但是如果(InterlockedDecrement(& mRefCount)== 0)不是吗?
我上面的例子错了吗?

在此先感谢您的意见和建议,以使我的课程完全线程安全.

解决方法:

您的分析不正确;您发布的代码正确使用了interlockedDecrement.

这是安全使用

 if(InterlockedDecrement(&mRefCount)==0)
           cleanup();

..但这确实会有您描述的问题

 InterlockedDecrement(&mRefCount);

 if (mRefCount==0)
           cleanup();

但是,使用delete this更有可能是问题的原因.您极不可能通过此处描述的“绝对肯定100%肯定”测试:
http://www.parashift.com/c++-faq-lite/delete-this.html

特别是,以下简单代码会引起混乱.

{
  RBuffer x;  // count is what... ? zero
  x.incRef(); // make count one
  x.decRef(); // make count zero, and deletes itself 
}  // now x goes out of scope, so destructor is called a second time = chaos! 

常规的“引用计数”惯用语涉及“共享对象”(带有计数)和引用共享对象的简单“引用对象”(不是C引用,尽管语义相似). “引用对象”的构造函数和析构函数负责在共享对象上调用incref / decref方法.因此,共享库会自动计算活动“参考对象”的数量.

标签:reference-counting,c,multithreading
来源: https://codeday.me/bug/20191011/1892281.html