[英]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.