2013-11-24 24 views
4

MyClass有一個成員函數需要返回它的'成員變量,而且這個函數必須是線程安全的,所以我用一個互斥量來保護數據。哪個會先執行,RAII還是函數返回值

我有兩個實現如下:

版本1:

string MyClass::name() { 
    m_mutex.lock(); 
    string temp = m_name; 
    m_mutex.unlock(); 
    return temp; 
} 

版本2:

string MyClass::name() { 
    MutexLocker lock(mutex); 
    return m_name; 
} 

我知道,第1版沒有問題,但我需要鍵入更碼。

問題是,我不確定版本2是否正確。在線程訪問m_name之前,互斥鎖是否會被釋放?

+2

既然您已經知道版本2是正確和安全的,那麼我可以認爲版本1可能是不安全的,就像在任何可能的異常情況下未使用RAII封裝保護的操作一樣(並疏忽釋放資源)。 RAII版本不僅可以減少輸入的工作量,還可以使您的代碼非常安全。這就是我所說的雙贏! –

回答

13

該版本2也是正確的(實際上,這是更好比第一個版本!)。

在通過本地對象的析構函數釋放互斥鎖之前,先複製該值。相反是不可能的,因爲本地對象在超出作用域時會被破壞,但是您必須注意return語句必須在作用域中執行,所以它必須在破壞之前發生。相反,在本地對象超出範圍之後,不能執行return語句。

從調用堆棧的角度來看,當堆棧開始展開時,本地對象被銷燬,但包含return語句的函數在堆棧展開之前很長時間才執行。這確保m_name在釋放互斥之前被複制。

還是覺得這個簡單的代碼:

std::string f() 
{ 
    std::string s = "Nawaz"; 
    return s; //Think of this line! 
} 

s後其銷燬複製 ?這甚至有可能嗎?如果s複製其銷燬?

1.或者更好地說,移動了。 :-)

+1

很高興知道RAII在這種看似不利的情況下不會失敗。 –

+2

@MarkGarcia:這根本不是邊緣案例。如果它不同,它將無法返回任何複雜的局部變量。 – Puppy

+0

實際上,我認爲版本2不僅好,而且實際上是更安全的方法。如果在鎖定和解鎖之間拋出異常,互斥鎖將永遠不會解鎖。 –

相關問題