我正在努力思考如何确保对象引用计数是线程安全的。
class MyObject{
//Other implementation details
private:
mutable volatile LONGLONG * m_count;
IData * m_data;
};
假设有必要的类声明,只是保持简单。这里是拷贝构造函数和析构函数的实现。
MyObject::MyObject(const MyObject& rhs) : m_count(rhs.m_count), m_data(rhs.m_data){
InterlockedIncrement64(m_count);
}
MyObject::~MyObject(){
if(InterlockedDecrement64(m_count) == 0)
delete m_data;
}
这个线程安全吗?如何看到复制构造函数的 intilization 列表,原子与否?这还重要吗?我应该在初始化列表中设置计数的递增值(这可能吗)?
就目前而言,这已经足够好了。我认为它是,否则,我怎么能进入thread1
复制和thread2
同时销毁的场景count == 1
。线程之间必须进行握手,这意味着 thread1 必须在 thread2 的对象超出范围之前完全复制对象,对吗?
在阅读了其中一些回复后,我回去做了一些研究。Boost 非常相似地实现了它们的 shared_ptr。这是析构函数调用。
void release() // nothrow
{
if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
有些人建议在 boost 文档中明确指出分配不是线程安全的。我同意和不同意。我认为在我的情况下我不同意。我只需要threadA和threadB之间的握手。我认为某些回复中描述的某些问题在这里并不适用(尽管它们是我没有完全考虑过的令人大开眼界的回复)。
示例 ThreadA atach(SharedObject); //通过值传递的共享对象,计数递增等
ThreadB //接受对象,将其添加到共享对象列表中。ThreadB 位于一个计时器上,该计时器向所有 SharedObjects 通知一个事件。在通知之前,列表的副本由关键部分保护。CS被释放,副本被通知。
ThreadA 分离(SharedObject);//从对象列表中删除共享对象
现在,同时 ThreadB 正在对 SharedOjbect 进行单选,并且在 ThreadA 分离所述共享对象之前已经制作了列表的副本。一切都好吗?