引用计数类和多线程 [英] reference counted class and multithreading
问题描述
下面是我的引用计数类:
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(){
InterlockedIntrement(& 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)
//删除对象,不存在
delete(Rbuffer *)this;
// CRASH
崩溃的原因可能是(InterlockedDecrement & mRefCount))部分是原子,但 if(InterlockedDecrement(& mRefCount)== 0)不是?
上面的例子错了吗?
提前感谢您的意见和建议,使我的类完全线程安全。
您的分析不正确;您发布的代码正在使用 interlockedDecrement
。
这是一个安全使用
if(InterlockedDecrement(& mRefCount)== 0)
cleanup();
..但这确实会有你描述的问题
InterlockedDecrement(& mRefCount);
if(mRefCount == 0)
cleanup();
但是,使用删除此
更可能是问题的原因。你不可能通过这里描述的绝对肯定的100%肯定测试:
http://www.parashift.com/c++-faq-lite/delete-this.html
特别是,以下简单代码将导致混乱。
{
RBuffer x; // count是什么...? zero
x.incRef(); // make count one
x.decRef(); // make count zero,and deletes itself
} //现在x超出范围,所以析构函数被第二次调用= chaos!
一个正常的引用计数成语涉及一个共享对象 '引用对象'(不是C ++引用,虽然语义将是类似的),它们指的是共享对象。 引用对象的构造函数和析构函数负责调用共享对象上的 incref / decref
方法。因此,共享对象会自动计算活动引用对象的数量。
I 'm a novice in multithreading programing and i have still confusion with that.
Below is my reference counted class:
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);
}
};
is it fully thread safe? Can you exclude this situation:
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
The reasons of crashing could be that only (InterlockedDecrement(&mRefCount)) part is atomic, but if (InterlockedDecrement(&mRefCount)==0) not? Am i wrong with example above?
Thanks in advance for your opinions and advice to make my class fully thread safe.
Your analysis isn't right; The code you posted is using interlockedDecrement
correctly.
This is a safe use
if(InterlockedDecrement(&mRefCount)==0)
cleanup();
.. but this would indeed have the problem you described
InterlockedDecrement(&mRefCount);
if (mRefCount==0)
cleanup();
However, the use of delete this
is much more likely to be the cause of the problem. It's very unlikely you're passing the 'absolutely positively 100% sure' tests described here:
http://www.parashift.com/c++-faq-lite/delete-this.html
In particular, the following simple code would cause chaos.
{
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!
A normal "reference counting" idiom involves a 'shared object' (with the count), and simple 'reference objects' (not C++ references, although the semantics would be similar) which refer to the shared object. The constructors and destructors of the 'reference objects' are responsible for calling the incref/decref
methods on the shared object. So the shared object is automatically counting the number of active 'reference objects'.
这篇关于引用计数类和多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!