2012-11-07 37 views
2

我有線程列表執行命令離開臨界區

do 
{ 
    commandExec->criticalSection.EnterCS(); 
    if (!commandExec->commands.empty()) 
    { 
     commandExec->ExecuteCommand(commandExec->commands.front()); 
     commandExec->commands.pop_front(); 
    } 
    else 
     commandExec->criticalSection.SuspendThread(); 
    commandExec->criticalSection.LeaveCS(); 
} while (commandExec->maintainCommandExecution); 

及第二線程這增加了命令列表:在執行命令

​​

第一個線程可能會崩潰,因此臨界區不能被第二個線程訪問:

如果一個線程終止,而它擁有ac政治部分,關鍵部分的狀態是不確定的。 Source

那麼,什麼是處理這個問題的好辦法嗎? 我能想到的一些解決方案,但他們似乎棘手(添加第三線程,第二臨界區等)

(CriticalSection的它是CRITICAL_SECTION只是簡單的包裝)

+3

你需要什麼是所謂的範圍鎖定包裝是關鍵部分。它鎖定範圍條目(或手動),但保證在範圍退出時解鎖(如果鎖定),*包括通過例外*退出。 – WhozCraig

+2

你是什麼意思線程是「崩潰」?我認爲一個線程不會「崩潰」,只是一個進程。 –

+0

你是對的,它會崩潰整個過程,但單線程可以被外部進程終止。這使得我的問題沒那麼有意義,雖然... – lowliet

回答

2

您可以創建一個LockCriticalSection類,它在構造函數中鎖定關鍵部分,並在析構函數中解鎖關鍵部分。

然後,在您的代碼中,您將分配一個LockCriticalSection對象,以便在其中啓動鎖定。當對象LockCriticalSection超出範圍的臨界部分將被自動釋放(因爲該函數正確地終止或者由於一個異常的)

以下是需要鎖定和解鎖的臨界部的護理中的代碼:

/// \brief This class locks a critical section in the 
///   constructor and unlocks it in the destructor. 
/// 
/// This helps to correctly release a critical section in 
/// case of exceptions or premature exit from a function 
/// that uses the critical section. 
/// 
/////////////////////////////////////////////////////////// 
class LockCriticalSection 
{ 
public: 
     /// \brief Creates the object LockCriticalSection and 
     ///   lock the specified CRITICAL_SECTION. 
     /// 
     /// @param pCriticalSection pointer to the CRITICAL_SECTION 
     ///       to lock 
     /// 
     /////////////////////////////////////////////////////////// 
     LockCriticalSection(CRITICAL_SECTION* pCriticalSection): 
      m_pCriticalSection(pCriticalSection) 
     { 
      EnterCriticalSection(pCriticalSection); 
     } 

     /// \brief Destroy the object LockCriticalSection and 
     ///   unlock the previously locked CRITICAL_SECTION. 
     /// 
     /////////////////////////////////////////////////////////// 
     virtual ~LockCriticalSection() 
     { 
      LeaveCriticalSection(m_pCriticalSection); 
     } 
private: 
     CRITICAL_SECTION* m_pCriticalSection; 
}; 

這是從你的問題修改後的源代碼:

do 
{ 
    { 
     LockCriticalSection lock(&criticalSectionToLock); 
     while (!commandExec->commands.empty()) 
     { 
      commandExec->ExecuteCommand(commandExec->commands.front()); 
      commandExec->commands.pop_front(); 
     } 
    } // here the critical section is released 
    // suspend thread here 
} while (commandExec->maintainCommandExecution); 
+2

[你有一個析構函數,但沒有拷貝構造函數或賦值操作符](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-reeree)。通常這些是爲互斥鎖存儲器聲明和未定義的(因爲複製這樣的事情沒有意義)。另外,虛擬析構函數是不必要的。 – GManNickG

+0

如果線程退出而不釋放關鍵部分,關鍵部分將不會解鎖。 – ChrisW

+0

@ChrisW如果循環中發生異常,那麼關鍵部分將解鎖。然後,如果不處理異常,則整個過程將崩潰並且臨界區的狀態變得無關緊要。 –

2

您可以使用互斥,而不是關鍵部分(但請注意Understanding the consequences of WAIT_ABANDONED中列出的問題)。

+0

我也使用SleepConditionVariableCS暫停線程,所以我寧願保持這種方式。我目前正在嘗試作爲@WhozCraig建議的範圍鎖定關鍵部分,但如果這不起作用,我會嘗試互斥。 – lowliet