在多线程程序中增强weak_ptr以实现资源池

时间:2010-01-29 06:41:05

标签: c++ multithreading boost smart-pointers

我正在考虑使用boost :: weak_ptr来实现一个对象池,这样当没有人使用其中一个对象时它们就会被收获。但我担心的是,它是一个多线程环境,似乎最后一个shared_ptr与一个超出范围的对象和一个从weak_ptr构造的新shared_ptr之间存在竞争条件。通常情况下,您可以通过锁定或其他方式保护此类操作;但是,这里的重点是你不知道shared_ptr何时可能超出范围。

我是否误解了关于boost :: shared_ptr和boost :: weak_ptr的事情?如果没有,是否有人对如何做有任何好的建议?

感谢。

安德鲁

3 个答案:

答案 0 :(得分:11)

要使用weak_ptr,您通常需要通过构建shared_ptr来获取强引用。最后一步是原子的:您要么获得强引用,要么抛出bad_weak_ptr异常。 (或者,在lock()上调用weak_ptr,然后获取强引用或null。)

示例(lock();足以适应其他风格):

void do_something(weak_ptr<foo> weak) {
    // Grab strong reference
    shared_ptr<foo> strong(weak.lock());
    if (strong) {
        // We now have a strong reference to use
    } else {
        // No strong references left; object already freed
    }
}

答案 1 :(得分:3)

如果涉及线程安全,boost::weak_ptrboost::shared_ptr都是相似的:如果存在对象将在某处被破坏的风险,则它们不是线程安全的。如果boost::shared_ptr或weak_ptr中引用的对象在某处永久引用,则使用shared/weak ptrs可以没有任何风险。

但是如果某些操作要取消引用对象的最后一个实例,那么那时你就不能对weak_ptr进行一些操作了:特别是:你不能将weak_ptr分配给另一个weak_ptr因为它在内部使用shared_ptr。此外,您不能使用锁定,因为结果是未定义的。此外,expired()方法对于:它可能返回true是无效的,但是在代码的下一行,您的对象可能已经过期。

答案 2 :(得分:0)

是的,是的。在访问指针方面,Boost应该让一切安全;这是他们观点的一部分。

但是,如果您希望在最后一次shared_ptr退出之间以及想要创建下一个shared_ptr之间有延迟,那么您将获得一个空指针。 (如果你正确检查,你应该有一个适当的失败案例。)

但是你最终无法得到一个无效的shared_ptr