gpt4 book ai didi

C++:多线程和引用计数对象

转载 作者:可可西里 更新时间:2023-11-01 18:28:55 25 4
gpt4 key购买 nike

我目前正在尝试将单线程程序传递给多线程。该软件大量使用“refCounted”对象,这会导致多线程中出现一些问题。我正在寻找一些设计模式或可能解决我的问题的东西。

主要问题是线程之间的对象删除,通常删除只会减少引用计数,当refcount为零时,对象就会被删除。这在单线程程序中运行良好,并且通过复制大对象可以显着提高性能。

然而,在多线程中,两个线程可能想同时删除同一个对象,因为对象受互斥量保护,只有一个线程删除对象并阻塞另一个线程。但是当它释放互斥锁时,另一个线程会继续执行无效的(已释放的对象),这会导致内存损坏。

这是一个 RefCountedObject 类的例子

class RefCountedObject
{
public:
RefCountedObject()
: _refCount( new U32(1) )
{}

RefCountedObject( const RefCountedObject& obj )
: _refCount( obj._refCount )
{
ACE_Guard< ACE_Mutex > guard( _refCountMutex );
++(*_refCount);
}

~RefCountedObject()
{
Destroy();
}

RefCountedObject& operator=( const RefCountedObject& obj )
{
if( this != &obj )
{
Destroy();
ACE_Guard< ACE_Mutex > guard( _refCountMutex );
_refCount = obj._refCount;
++(*_refCount);
}

return *this;
}

private:
void Destroy()
{
ACE_Guard< ACE_Mutex > guard( _refCountMutex ); // thread2 are waiting here
--(*_refCount); // This cause a free memory write by the thread2
if( 0 == *_refCount )
delete _refCount;
}

private:
mutable U32* _refCount;
mutable ACE_Mutex _refCountMutex; // BAD: this mutex only protect the refCount pointer, not the refCount itself
};

假设两个线程要删除同一个 RefCountedObject,都在 ~RefCountedObject 中并调用 Destroy(),第一个线程已锁定互斥量,另一个正在等待。在第一个线程删除对象后,第二个线程将继续执行并导致空闲内存写入。

有人遇到过类似的问题并找到了解决方案吗?


感谢大家的帮助,我意识到我的错误:互斥量只是保护 refCount 指针,而不是 refCount 本身!我创建了一个受互斥保护的 RefCount 类。互斥量现在在所有 refCounted 对象之间共享。

现在一切正常。

最佳答案

如果计数是对象的一部分,那么如果一个线程可能试图增加引用计数而另一个线程试图删除最后,那么你就有了一个固有的问题引用。每个指向该对象的全局可访问指针的引用计数都需要有一个额外的值,因此如果您有一个指针,您始终可以安全地增加引用计数。

一个选择是使用boost::shared_ptr (see the docs) .您可以使用免费函数 atomic_loadatomic_storeatomic_exchangeatomic_compare_exchange(文档中明显没有)在访问共享对象的全局指针时确保适当的保护。一旦您的线程获得了指向特定对象的 shared_ptr,您就可以使用普通的非原子函数来访问它。

另一种选择是使用 Joe Seigh 的原子引用计数指针,来自他的 atomic_ptr_plus project

关于C++:多线程和引用计数对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/166125/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com