如何解决在锁定前后检查资源
我遇到过类似这样的简化代码
inline someClass* otherClass::getSomeClass()
{
if (m_someClass)
return m_someClass.get();
std::unique_lock<std::shared_mutex> lock(m_lock);
if (m_someClass)
return m_someClass.get();
m_someClass= std::make_unique<someClass>(this);
return m_someClass.get();
}
所以这似乎是一种确保创建 someClass 对象的线程安全性的模式。我在多线程方面没有太多经验,但是这段代码对我来说并不好看。有没有其他方法可以重写它,或者它应该是一种方式?
解决方法
这里最大的问题是您违反了 C++ 内存模型。在C++内存模型中,对同一数据的写操作和读操作必须同步。
前面的 m_someClass
正在读取互斥锁中写入的内容。
operator bool
上的 m_someClass
可能以某种方式是原子的。
此外,您的代码不会处理被销毁的对象。
如果它是原子的,那么您可能应该使用原子操作来更新它而不是锁。这种模式可能会导致创建“浪费”的对象;通常这值得移除锁的成本。
使m_someClass
成为std::atomic<std::shared_ptr<someClass>>
。
从 std::shared_ptr<someClass>
返回 getSomeClass
。
auto existing = m_someClass.load();
if (existing)
return existing;
auto created = std::make_shared<someClass>(this);
if (
m_someClass.compare_exchange_strong(existing,created)
) {
return created;
} else {
return existing;
}
如果两个线程同时尝试获取,则它们都可以创建一个新的 someClass
,但只有一个会持久化,另一个会被丢弃,并且函数将返回持久化的那个。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。