提升shared_ptr容器问题

时间:2020-03-06 14:32:03  来源:igfitidea点击:

假设我有一个多线程应用程序使用的指针容器(std :: vector)。在向容器添加新的指针时,使用关键部分(boost :: mutex)保护代码。一切都很好。该代码应该能够将这些指针之一返回给线程进行处理,但是另一个单独的线程可以选择删除这些指针之一,而这些指针可能仍在使用中。例如。:

thread1()
{
    foo* p = get_pointer();
    ...
    p->do_something();
}

thread2()
{
    foo* p = get_pointer();
    ...
    delete p;
}

因此线程2可以在线程1使用它时删除该指针。可恶的。

因此,我想使用Boost共享ptrs的容器。 IIRC这些指针将被引用计数,因此,只要我返回共享ptrs而不是原始指针,就从容器中删除一个指针就不会真正释放它,直到最后一次使用超出范围为止。 IE。

std::vector<boost::shared_ptr<foo> > my_vec;

thread1()
{
    boost::shared_ptr<foo> sp = get_ptr[0];
    ...
    sp->do_something();
}

thread2()
{
    boost::shared_ptr<foo> sp = get_ptr[0];
    ...
    my_vec.erase(my_vec.begin());
}

boost::shared_ptr<foo> get_ptr(int index)
{
    lock_my_vec();
    return my_vec[index];
}

在上面的示例中,如果线程1在线程2调用擦除之前获取了指针,指向的对象是否仍然有效?线程1完成后,它实际上不会被删除吗?请注意,将通过关键部分访问全局向量。

我认为这是shared_ptrs的工作方式,但我需要确定。

解决方案

为了提高boost :: shared_ptr的线程安全性,我们应该检查此链接。它不保证安全,但在许多平台上都可以使用。修改std :: vector不是安全的AFAIK。

另外,如果我们同步了对向量的访问(如原始原始指针建议中那样),则使用是安全的。否则,我们可能会在其他受访者提供的链接中违反示例4.

In the above example, if thread1 gets the pointer before thread2 calls erase, will the object pointed to still be valid? It won't actually be deleted when thread1 completes?

在示例中,如果线程1在线程2之前获得了指针,则线程2将不得不在函数的开始处等待(由于锁定)。因此,是的,指向的对象仍然有效。但是,我们可能需要在访问my_vec的第一个元素之前确保它不为空。