2014-01-22 48 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