以下是代码示例:
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;
}
};
建议尽管编译器优化,但boost::shared_ptr
上的A::a
拷贝构造函数调用将在boost::lock_guard
析构函数调用之前。
那么,拨打A::clone_a()
是否安全?
答案 0 :(得分:5)
如果“安全”,则表示您不会在a
上获得数据竞赛,那么是。就像你说的那样。
然而,正如您可能知道的那样,它不会保护对*a
(或*clone_a()
)的进一步访问。我不确定,为什么这个方法称为“克隆”,因为它不会克隆任何东西。
答案 1 :(得分:2)
是的,这段代码是安全的。如果你引用shread_ptr Thread-Safety,你可以看到对线程局部shared_ptr对象的线程写访问就好了。
在上面的代码中,对成员shared_ptr的访问需要锁定,因为它可以被多个线程访问。返回临时的副本是在锁内完成的,因此你在那里安全。其他线程无法看到该临时值,因此您可以安全地将其复制到其他shared_ptr中。
现在,选择clone_a
作为函数名称可能是错误的。您没有克隆底层对象,您只是获取shared_ptr的副本。所以我假设您打算共享相同的底层“int”。
答案 2 :(得分:-1)
如果您使用返回值,则不会。返回值本身是一个
临时的,其寿命超出了函数的末尾;它
将在调用的完整表达式结束时被破坏
A::clone_a
。所以如果你写的东西如下:
shared_ptr<int> newA = object->clone_a();
,形式语义将由临时返回
要object->clone_a()
复制到newA
,请将其复制到-D
somthing
调用者(因此不受互斥锁保护)。在这种特殊情况下,你
可能因为RVO而侥幸逃脱,但这不一定是
案例,还有其他情况,RVO无法干预。
如果你担心的只是指针的副本,我很确定
如果您设置了正确的编译器选项(boost::shared_ptr
),{{1}}将以原子方式运行。在
在这种情况下,您根本不需要互斥锁。