2012-07-25 15 views
5

在嘗試從頭開始創建線程安全的容器類時,遇到了從訪問方法返回值的問題。例如,在Windows中:C++中的關鍵部分和返回值

myNode getSomeData() 
{ 
    EnterCriticalSection(& myCritSec); 
    myNode retobj; 
    // fill retobj with data from structure 
    LeaveCriticalSection(& myCritSec); 
    return retobj; 
} 

現在我想,這種類型的方法是不是所有線程安全的,因爲代碼釋放臨界區的另一個線程能夠一起去,並立即在第一線覆蓋前retobj後回報。那麼,以線程安全的方式將retobj返回給調用者的優雅方式是什麼?

+1

但retobj存儲在堆棧上?除非聲明爲「靜態」,否則您應該不會覆蓋複製的數據。 – 2012-07-25 15:23:34

+0

除非出現奇怪的情況,'retobj'應該在堆棧上,並且每個線程都應該有自己的堆棧。當您使用預先分配的內存並且必須鎖定訪問以防止共享時,此種競爭條件更爲常見。 – ssube 2012-07-25 15:23:43

+0

@inface,確定好點,只要返回值存儲在堆棧中,我就很好。 – ThomasMcLeod 2012-07-25 15:25:58

回答

7

不,它是線程安全的,因爲每個線程都有它自己的堆棧,這就是retobj所在的位置。

但是,它當然不是例外安全的。將關鍵部分包裹在RAII風格的對象中會有所幫助。喜歡的東西...

class CriticalLock : boost::noncopyable { 
    CriticalSection &section; 

public: 
    CriticalLock(CriticalSection &cs) : section(cs) 
    { 
    EnterCriticalSection(section); 
    } 

    ~CriticalLock() 
    { 
    LeaveCriticalSection(section); 
    } 
}; 

用法:

myNode getSomeData() 
{ 
    CriticalLock lock(myCritSec); // automatically released. 
    ... 
} 
2

這是C++,retobj具有自動存儲類型,所以它存儲在堆棧中。

每個線程都有自己的堆棧,因此另一個線程在返回之前無法將retobj的值打開。