2011-10-06 36 views
4

下面是一个代码示例:按值返回由互斥量守护的shared_ptr是否安全?

class A { 
    boost::mutex a_mutex; 
    boost::shared_ptr<int> a; 

    boost::shared_ptr<int> clone_a(void) { 
    boost::lock_guard<boost::mutex> lock(a_mutex); 
    return a; 
    } 
}; 

的建议是,在A::aboost::shared_ptr拷贝构造函数的调用将先于boost::lock_guard析构函数调用,尽管编译器优化。 那么,拨打A::clone_a()安全吗?

+0

dupe http://stackoverflow.com/questions/692438/is-boost-shared-ptr-xxx-thread-safe? – eudoxos

+0

你能解释一下为什么你担心它可能不好吗? – curiousguy

回答

5

如果用“安全”表示你不会在a上得到数据竞赛,那么是的。这完全如你所说。您可能知道,它不会保护对*a(或*clone_a())的进一步访问。我不确定,为什么该方法称为“克隆”,因为它不克隆任何东西。

-1

如果使用返回值,则不适用。返回值本身是一个 临时值,它的生命周期超出函数的结尾;它将在完整表达式的末尾处被销毁,其中 A::clone_a。所以,如果你写的东西,如:

shared_ptr<int> newA = object->clone_a(); 

,形式语义将是暂时的 object->clone_a()回到复制到newA,在 调用者(以及由互斥体,无保护)的情况下。在这种情况下,您因为RVO而可能会逃脱,但这并不一定是 的情况,还有其他RVO无法干预的情况。

如果所有你担心的是指针的副本,我很肯定 ,如果你设置正确的编译器选项(-D somthing),boost::shared_ptr将以原子方式行为。在 这种情况下,根本不需要互斥锁。

+0

这里缺少一些东西。第一个副本将在锁定段内的'clone_a'函数内完成。这是从成员变量复制到返回。返回的临时数据将被复制到新变量中。我在这里没有看到任何问题(当然我不知道clone_a实际上应该做什么)。 –

+0

@ edA-qamort-ora-y从成员变量到编译器放置返回值的位置的第一个副本发生在函数中,并受到保护。第二个副本,从编译器将返回值放到值应该去的地方,发生在调用站点,并且不受保护。 –

+1

但这就是问题:从什么保护?传递和复制shared_ptr,甚至是临时对象是完全安全的,每一个都可以正确地维护引用计数。也就是说,你的'newA'保证指向锁定段内引用的同一个对象。 –

2

是的,这段代码是安全的。如果您参考shread_ptr Thread-Safety,您可以看到线程化写入对线程本地shared_ptr对象的访问非常好。

在上面的代码中,对成员shared_ptr的访问需要锁,因为它可以被多个线程访问。复制到临时返回是在锁内完成的,因此你在那里安全。该临时文件不能被其他线程看到,所以你可以安全地将它复制到其他shared_ptr文件中。

现在或许选择clone_a作为函数名是错误的。您不克隆底层对象,您只需获取shared_ptr的副本。所以我假设你打算共享相同的底层“int”。

相关问题