按值返回由互斥锁保护的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::a
的 boost::shared_ptr
复制构造函数调用将先于 boost::lock_guard
> 尽管编译器优化,析构函数调用。 那么,调用 A::clone_a()
是否安全?
Here is a code sample:
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;
}
};
The suggestion is that the boost::shared_ptr
copy constructor call on A::a
will precede the boost::lock_guard
destructor call despite of the compiler optimizations.
So, is it safe to call A::clone_a()
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果“安全”意味着您不会在
a
上发生数据争用,那么是的。正是如你所说。但是,您可能知道,它不会保护对
*a
(或*clone_a()
)的进一步访问。我不确定为什么该方法被称为“克隆”,因为它不克隆任何东西。If by "safe" you mean you won't get data races on
a
, then yes. It is exactly as you say.However, it won't protect further accesses to
*a
(or*clone_a()
), as you probably know. I'm not sure, why is the method called "clone", as it doesn't clone anything.是的,这段代码是安全的。如果您参考 shread_ptr 线程安全,您可以看到,对线程本地shared_ptr对象的线程写访问就很好了。
在上面的代码中,对成员shared_ptr的访问需要锁,因为它可以被多个线程访问。到返回临时对象的复制是在锁内完成的,因此您在那里是安全的。该临时对象无法被其他线程看到,因此此时您可以安全地将其复制到其他共享指针。
现在,选择
clone_a
作为函数名可能是错误的。您没有克隆底层对象,您只是获得了shared_ptr的副本。所以我假设您打算共享相同的底层“int”。Yes, this code is safe. If you refer to shread_ptr Thread-Safety you can see that threaded write access to thread-local shared_ptr objects is just fine.
In your code above the access to the member shared_ptr requires the lock, since it could be accessed by multiple threads. The copy to the return temporary is done within the lock, thus you're safe there. That temporary cannot be seen by other threads so at that point you are safe to copy it to other shared_ptr's.
Now perhaps the choice of
clone_a
as a function name is wrong. You aren't cloning the underlying object, you are simply getting a copy of the shared_ptr. So I am assuming you intend on sharing the same underlying "int".如果您使用返回值则不会。返回值本身是一个
临时的,其生命周期超出了函数的结尾;它
将在调用的完整表达式的末尾被破坏
A::clone_a
。因此,如果您编写类似: 的内容,形式语义将适用于由
object->clone_a()
被复制到newA
中,在调用者(因此不受互斥锁的保护)。在这种特殊情况下,您
可能会因为 RVO 而逃脱惩罚,但这不一定是
情况,还有其他情况 RVO 无法干预。
如果您担心的只是指针的副本,我很确定
如果您设置正确的编译器选项(
-D
),somthing
boost::shared_ptr
将以原子方式运行。在在这种情况下,您根本不需要互斥锁。
Not if you use the return value. The return value itself is a
temporary, whose lifetime extends beyond the end of the function; it
will be destructed at the end of the full expression which calls
A::clone_a
. So if you write something like:, the formal semantics will be for the temporary returned by
object->clone_a()
to be copied intonewA
, in the context of thecaller (and so unprotected by the mutex). In this particular case, you
may get away with it because of RVO, but that won't necessarily be the
case, and there are other cases where RVO can't intervene.
If all you're worried about is the copy of the pointer, I'm pretty sure
that if you set the right compiler options (
-D
),somthing
boost::shared_ptr
will behave atomically. Inthis case, you don't need the mutex at all.