2014-01-22 132 views
0

在我的多線程服務器中,我有somefunction(),它需要使用EnterCriticalSection來保護兩個彼此獨立的其他全局數據。使功能異常安全

somefunction() 
{ 
    EnterCriticalSection(&g_List); 
    ... 
    EnterCriticalSection(&g_Variable); 
    ... 
    LeaveCriticalSection(&g_Variable); 
    ... 
    LeaveCriticalSection(&g_List); 
} 

遵循更好的程序員的建議我打算使用RAII包裝。例如:

class Locker 
{ 
    public: 
    Locker(CSType& cs): m_cs(cs) 
    { 
    EnterCriticalSection(&m_cs); 
    } 
    ~Locker() 
    { 
    LeaveCriticalSection(&m_cs); 
    } 
    private: 
    CSType& m_cs; 
} 

我的問題:它是確定改造somefunction()這個? (把2個儲物櫃放在一個功能中):

somefunction() 
{ 
// g_List,g_Variable previously initialized via InitializeCriticalSection 

    Locker lock(g_List); 
    Locker lock(g_Variable); 
    ... 
    ... 
} 

回答

1

您目前的解決方案有潛在的dead lock的情況。如果您有兩個(或更多)CSType這將按這種方式以不同的順序鎖定,您將最終死鎖。最好的辦法是自動鎖定它們。你可以在boost thread庫中看到這個例子。 shared_lockunique_lock可用於延遲模式,以便首先爲所有互斥對象準備所有raii對象,然後將它們全部以原子方式鎖定在一次調用lock函數中。

+0

如果我始終保持相同的鎖定順序,那該怎麼辦? – maciekm

+0

是的,但實踐表明,跨越任何不平凡的應用程序確實很難做到。 – tumdum

1

只要你保持鎖定順序相同,你的線程就OK了。你真的需要同時鎖定它們嗎?你也可以通過作用域鎖來添加作用域來控制何時解鎖,如下所示:

{ 
    // use inner scopes to control lock duration 
    { 
     Locker lockList (g_list); 
     // do something 
    } // unlocked at the end 

    Locker lockVariable (g_variable); 
     // do something 
} 
+0

如果我把這些額外的括號,所有由托馬斯Kłak提到的麻煩消失? – maciekm

+1

不,您需要在所有線程中保持相同的鎖定順序,我給出的代碼僅僅是顯示範圍鎖定允許您執行的操作。 – mindo