2012-12-10 61 views
4

我是新來的助推庫,它是如此驚人的庫!另外,我對互斥體很陌生,所以如果我犯了一個新手錯誤,請原諒我。提升互斥鎖定在同一線程上

無論如何,我有兩個函數叫做FunctionOneFunctionTwoFunctionOneFunctionTwo由不同的線程異步調用。所以發生了什麼:在FunctionOne中,我在函數的開頭鎖定了全局互斥鎖,並在函數結束時解鎖了全局互斥鎖。 FunctionTwo同樣的事情。

現在問題出現了:有時,FunctionOneFunctionTwo被稱爲間隔少於幾毫秒(並非總是如此)。所以,FunctionOne開始執行,並通過FunctionTwo中途執行。當FunctionTwo鎖定互斥鎖時,FunctionOneFunctionTwo所在的整個線程停止,所以FunctionOne中途卡住,線程永遠等於FunctionTwo本身。因此,總結一下:

  • 函數1鎖定互斥鎖並開始執行代碼。
  • 函數2在幾秒後被調用並鎖定互斥鎖,凍結線程func 1和2。
  • 現在func 1卡住了一半,線程被凍結,所以func 1永遠不會結束,互斥鎖永遠被鎖定,等待func 1完成。

在這種情況下,人們會做什麼?這裏是我的代碼:

boost::mutex g_Mutex; 
lua_State* L; 

// Function 1 is called from some other thread 
void FunctionOne() 
{ 
    g_Mutex.lock(); 

    lua_performcalc(L); 

    g_Mutex.unlock(); 
} 

// Function 2 is called from some other thread a few ms later, freezing the thread 
// and Function 1 never finishes 
void FunctionTwo() 
{ 
    g_Mutex.lock(); 

    lua_performothercalc(L); 

    g_Mutex.unlock(); 
} 
+2

如果f1和f2由同一個線程調用,那麼如何F2可以稱得上而F1仍在進行中?你的意思是從f1調用f2嗎? –

+0

這就是我所困惑的。我確信FunctionOne和FunctionTwo是從一個單獨的線程調用的。但是,我做了以下操作:'printf(「Function:%s,time:%f」,__FUNCTION__,globals-> currentTime());'有時候這兩個函數都會立即調用(並且應用程序崩潰以便寫入相同的資源),並通過一個互斥體,應用程序在自己的線程上等待。 – arao6

+0

-1這個問題需要一個SSCCE。見http://www.sscce.org/正如你在浪費你自己的時間,也是爲了我們的。 **更新**嗯。爲什麼RSS提要中的舊問題? – sehe

回答

8

難道這些功能打算重入,這樣FunctionOne會調用自身或FunctionTwo同時持有互斥?反之亦然,FunctionTwo鎖定互斥鎖,然後在鎖定互斥鎖的同時調用FunctionOne/FunctionTwo?

  • 如果不是,那麼你不應該從同一個線程調用這兩個函數。如果你打算FunctionTwo阻塞,直到FunctionOne完成,那麼在同一個線程中調用它是一個錯誤。如果lua_performcalc最終調用FunctionTwo,就會發生這種情況。這將是他們可以在同一個線程上調用的唯一方法。

  • 如果是這樣,那麼你需要一個recursive_mutex。常規互斥鎖只能鎖定一次;從同一個線程再次鎖定它是一個錯誤。遞歸互斥鎖可以被單個線程多次鎖定,並被鎖定,直到線程調用解鎖相同的次數。

無論哪種情況,都應該避免顯式調用鎖定和解鎖。如果拋出異常,互斥鎖將無法解鎖。最好使用RAII式鎖定,如下所示:

{ 
    boost::recursive_mutex::scoped_lock lock(mutex); 

    ...critical section code... 

    // mutex is unlocked when 'lock' goes out of scope 
} 
+0

即使需要重新調用,你也可以避免遞歸互斥。 – 2012-12-10 17:59:56

+0

這兩個函數保證永遠不會互相調用或它自己,但是這兩個函數使用相同的資源和子例程(例如lua_getglobal,lua_gettop等)。當我記錄FunctionOne和FunctionTwo運行的時間時,它們被不同的線程同時調用(到小數點後8位),線程永遠掛起。有時這些函數相隔幾毫秒,然後就沒有問題了(通常情況下,除非時間差很小)。我不認爲兩個函數可以在同一個線程上同時執行,所以我不知道爲什麼會發生這種情況。 – arao6

3

你的描述是不正確的。一個互斥鎖不能被鎖定兩次。你有一個不同的問題。

  • 鎖定互斥鎖時檢查再入口。
  • 檢查異常

,以避免與異常的問題,你應該使用boost::mutex::scoped_lockRAAI

+0

使用scoped_lock,等待的問題消失了,但現在這兩個函數似乎一次寫入同一資源。顯然有一些我不理解。 :( – arao6

+0

如果scoped_lock確實解決了死鎖,那麼'lua_performcalc(L);'可能會引發 – stefan

+0

當我記錄時間時,FunctionOne和FunctionTwo有時會同時觸發(至小數點後8位),lua_performcalc和lua_performothercalc嘗試寫入相同的資源和崩潰,有時當它們相距幾毫秒時,它們也會崩潰,只有當兩個函數相距幾百毫秒時,它們纔會崩潰,當我使用'g_Mutex.lock() '相反,線程自身掛起,我認爲兩個函數不能同時在同一個線程上執行,所以我不知道爲什麼會發生這種情況。 – arao6