簡體   English   中英

關鍵部分和C ++中的引用返回值

[英]Critical Sections and return value by reference in C++

我已經在2012年問過一個非常類似的問題。

C ++中的關鍵節和返回值

我也想安全地訪問容器線程,而是通過引用返回緩存的版本。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM