[英]Critical Sections and return value by reference in C++
我已经在2012年问过一个非常类似的问题。
我也想安全地访问容器线程,而是通过引用返回缓存的版本。
struct Container {
const Data& getSomeData() const {
EnterCriticalSection(& myCritSec);
if (update) {
cache.calulatefromcontainer();
}
// fill retobj with data from structure
LeaveCriticalSection(& myCritSec);
return cache;
}
private:
mutable Data cache;
};
问题是,“返回缓存”行不再受保护。 是否可以通过引用安全地返回“缓存”线程?
您必须考虑关键部分实际上在保护什么。
在您的代码中, myCritSec
正在保护容器。 但值得注意的是,它不能保护cache
成员变量。 那不是因为return cache;
行,但是因为您正在返回对其的引用,所以它可以不受客户端代码的限制而被使用,而其他线程再次调用getSomeData()
并对其进行修改。
一种解决方案是返回数据的副本。
另一个解决方案是,每个可用于从Data
获取信息的公共函数都将以某种方式使用父容器的myCritSec
。 这种方法的问题在于,参加比赛非常容易。 例如:
class Data
{
public:
int getA() const
{
int res;
EnterCriticalSection(parentCS);
res = getAunlocked();
LeaveCriticalSection(parentCS);
return res;
}
int getB() const
{
int res;
EnterCriticalSection(parentCS);
res = getBunlocked();
LeaveCriticalSection(parentCS);
return res;
}
};
然后在用户代码中:
const Data &data = container.getSomeData();
if (data.getA() == data.getB()) // <--- RACE!!!
{
}
由于对getA()
和getB()
的调用分别是锁定和解锁CS,因此另一个线程可能会在两者之间修改数据并创建竞争条件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.