2012-05-23 54 views
2

我正在評審一位同事的Visual Studio 2008 C++ 03應用程序應用程序,並且我遇到了一個線程同步原語的實現(見下文)。這個同步對象實現線程安全嗎?

假設SyncObject正確實施,是在下面的代碼中使用布爾值來知道資源是否鎖定或解鎖線程安全?如果不是,你可以通過一個「ThreadA」來做到這一點,而「ThreadB」做到這一點,所以我理解你的邏輯?

class CMyLock 
{ 
public: 
    CMyLock(SyncObject* object) 
     : object_(object), acquired_(false) 
    { 
    }; 

    // return true if the resource is locked within the given timeout period 
    bool Lock(DWORD dwTimeOut = INFINITE) 
    { 
     acquired_ = object_->Lock(dwTimeOut); 
     return acquired_; 
    }; 

    // return true if the resource is unlocked 
    bool Unlock() 
    { 
     if (acquired_) 
      acquired_ = !object_->Unlock(); 
     return !acquired_; 
    }; 

    // return true if the resource is locked 
    bool IsLocked() { return acquired_; }; 

private: 
    bool acquired_; 
    // some thread synchronization primitive 
    SyncObject* object_; 
}; 
+0

不使用RAII =失敗。 –

+0

不,它可以存儲在註冊表,緩存和任何其他因爲優化而存在的內容。 –

+0

你能走過我會遇到失敗的情況嗎? – PaulH

回答

3

它不是線程安全的。

後直接m_pObject->Unlock()回報,另一個線程等待m_pObject->Lock(dwTimeOut)可以返回,並設置m_bAcquired爲true,則解鎖線程設置m_bAcquired爲假,並錯誤地覆蓋鎖定狀態(當對象被鎖定IsLocked將返回false)。

1

簡短的回答:沒有

你需要讀鎖過,或者你可能看到一個陳舊的狀態。

1

不,它不是 - 至少從我能看到的。可能發生的情況是一個線程調用鎖並獲取鎖,另一個線程在線程更新之前訪問m_bAcquired,導致鎖。

這就是爲什麼你需要一個閱讀鎖以及Matthieu M.說。

答:鎖定 m_pObject被鎖定後,但被設置 乙m_bAcquired前:IsLocked - >返回false A - 仍處於鎖定:m_pObject =真

所以B有虛假信息。其他問題: 解鎖依賴m_bAcquired。

我認爲這個對象意味着從一個單一的線程內使用。所以每個線程都有自己的CSingleLock實例,但它們都使用相同的SyncObject。在這種情況下,只有SyncObject需要線程安全並且可以工作。

2

我看到這個代碼有幾個嚴重的問題。在代碼審查中,我會拒絕它。

  1. 目前還不清楚這個班的目的是什麼。它可能是一個基元的瘦代理。它可能是一個自動儲物櫃。無論哪種情況,設計都是錯誤的,文檔(沒有)沒有詳細說明。

  2. 它不使用RAII。這是一個好主意,不管這個目標是什麼意圖,但在自動櫃子的情況下,這是非常重要的。

  3. 它保留它自己的狀態,它可能與同一線程中的其他實例不同步。例如,如果您在線程A上創建了此對象的2個實例,請將其中一個設置爲locked並檢查另一個的狀態,它應該說明爲locked但它不會。

  4. 可能最重要的是,它正在重新發明輪子。