依赖“use_count()”是否安全?重用“shared_ptr”多线程应用程序中的内存?
我正在审查一些旧代码,我对这段代码的可靠性表示怀疑。不幸的是,原来的开发者已经不在了,所以我无法向他寻求解释。
下面的类负责根据需要为struct
分配内存,而不是在多个地方和多个线程中使用。 getStruct()
仅从一处和一个线程调用,但返回的 std::shared_ptr
会分派到多个线程。作为一种优化,我们尝试重用之前创建的 struct,而不是丢弃旧的。
#include <vector>
#include <memory>
#include <algorithm>
struct SomeHeavyStruct
{};
class HeavyStructProvider
{
public:
std::shared_ptr<SomeHeavyStruct> getStruct()
{
auto it =
std::find_if(m_buffer.cbegin(), m_buffer.cend(), [&](const auto& pointer) {
return pointer.use_count() == 1;
});
if (it != m_buffer.cend()) {
auto pointer = *it;
return pointer;
}
auto newStruct = std::make_shared<SomeHeavyStruct>();
m_buffer.push_back(newStruct);
return newStruct;
}
private:
std::vector<std::shared_ptr<SomeHeavyStruct>> m_buffer;
};
我担心的是,在阅读 std::shared_ptr
文档,我看到以下内容:
在多线程环境中,use_count 返回的值是近似值(典型实现使用
memory_order_relaxed
加载)
并且:
如果 use_count 返回 1,则没有其他所有者。 [...] 在多线程环境中,这并不意味着该对象可以安全地修改,因为以前的共享所有者对托管对象的访问可能尚未完成,并且因为新的共享所有者可能会同时引入,例如通过 std: :weak_ptr::锁。
知道 std::shared_ptr
如果我必须重构它代码,建议的方法是什么?使用受 mutex
保护的自定义 Deleter
是一种可行的方法(使用自定义标志有效地标记可重用结构,而不是依赖 use_count()< /代码>)?
I'm reviewing some old code and I have doubt about the reliability of this one. Unfortunately, the original developer is no longer around so I can't ask him for an explanation.
The following class is in charge of allocating memory on demand for an struct
than is used in multiple places and from multiple threads. The getStruct()
is called from one place and one thread only, but the returned std::shared_ptr<SomeHeavyStruct>
is dispatched to multiple threads. As an optimization, an attempt is made to try to re-use previously created struct
instead of throwing away old ones.
#include <vector>
#include <memory>
#include <algorithm>
struct SomeHeavyStruct
{};
class HeavyStructProvider
{
public:
std::shared_ptr<SomeHeavyStruct> getStruct()
{
auto it =
std::find_if(m_buffer.cbegin(), m_buffer.cend(), [&](const auto& pointer) {
return pointer.use_count() == 1;
});
if (it != m_buffer.cend()) {
auto pointer = *it;
return pointer;
}
auto newStruct = std::make_shared<SomeHeavyStruct>();
m_buffer.push_back(newStruct);
return newStruct;
}
private:
std::vector<std::shared_ptr<SomeHeavyStruct>> m_buffer;
};
My concern is that while reading the std::shared_ptr<T>::use_count()
documentation, I'm seeing the following:
In multithreaded environment, the value returned by use_count is approximate (typical implementations use a
memory_order_relaxed
load)
And also:
If use_count returns 1, there are no other owners. [...] In multithreaded environment, this does not imply that the object is safe to modify because accesses to the managed object by former shared owners may not have completed, and because new shared owners may be introduced concurrently, such as by std::weak_ptr::lock.
Knowing that the std::shared_ptr<SomeHeavyStruct>
is used from multiple threads, am I right to assume the current implementation is prone to unexpected behavior?
If I had to refactor this code, what would be a suggested approach? Is using a custom Deleter
protected by a mutex
the way to go (to effectively mark re-usable struct with a custom flag instead of relying on use_count()
)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论