簡體   English   中英

互斥鎖無法獲取鎖

[英]Mutex can't acquire lock

我有一個問題,我的功能之一無法獲取我使用的2個互斥鎖之一上的鎖。 我在VC ++ 2010中進行了基本調試,設置了一些斷點,並且似乎在任何地方獲得了鎖都可以將其解鎖。

使用互斥鎖的代碼如下:

#define SLEEP(x) { Sleep(x); }
#include<windows.h>

    void Thread::BackgroundCalculator( void *unused ){
    while( true ){
        if(MUTEX_LOCK(&mutex_q, 5) == 1){
            if(!QueueVector.empty()){
//cut
                MUTEX_UNLOCK(&mutex_q);
                    //cut
                while(MUTEX_LOCK(&mutex_p,90000) != 1){}
                //cut
                MUTEX_UNLOCK(&mutex_p);
            }

        }
        SLEEP(25);
    }
}

然后在其他地方:

PLUGIN_EXPORT void PLUGIN_CALL
    ProcessTick(){
    if(g_Ticked == g_TickMax){
        if(MUTEX_LOCK(&mutex_p, 1) == 1){
            if(!PassVector.empty()){
                PassVector.pop();
            }
            MUTEX_UNLOCK(&mutex_p);
        }
        g_Ticked = -1;
    }
    g_Ticked += 1;
}

static cell AMX_NATIVE_CALL n_CalculatePath( AMX* amx, cell* params ){
    if(MUTEX_LOCK(&mutex_q,1) == 1){
        QueueVector.push_back(QuedData(params[1],params[2],params[3],amx));
        MUTEX_UNLOCK(&mutex_q);
        return 1;
    }
    return 0;
}

在里面:

PLUGIN_EXPORT bool PLUGIN_CALL Load( void **ppData ) {
    MUTEX_INIT(&mutex_q);
    MUTEX_INIT(&mutex_p);
    START_THREAD( Thread::BackgroundCalculator, 0);
    return true;
}

一些變量和函數:

int MUTEX_INIT(MUTEX *mutex){
    *mutex = CreateMutex(0, FALSE, 0);
    return (*mutex==0);
}

int MUTEX_LOCK(MUTEX *mutex, int Timex = -1){
    if(WaitForSingleObject(*mutex, Timex) == WAIT_OBJECT_0){
        return 1;
    }
    return 0;
}
int MUTEX_UNLOCK(MUTEX *mutex){
    return ReleaseMutex(*mutex);
}

MUTEX mutex_q = NULL;
MUTEX mutex_p = NULL;

並定義:

#   include <process.h>
#   define OS_WINDOWS
#   define MUTEX HANDLE
#   include <Windows.h>
#   define EXIT_THREAD() { _endthread(); }
#   define START_THREAD(a, b) { _beginthread( a, 0, (void *)( b ) ); }

線程頭文件:

#ifndef __THREAD_H
#define __THREAD_H

class Thread{
    public:
                                    Thread                      ( void );
                                   ~Thread                      ( void );
    static void                     BackgroundCalculator        ( void *unused );

};

#endif

好吧,我似乎找不到問題。 調試后,我想通過以下代碼“強制”獲取鎖(從典當抽象機中獲取):

if (strcmp("/routeme", cmdtext, true) == 0){
    new fromnode = NearestPlayerNode(playerid);
    new start = GetTickCount();
    while(CalculatePath(fromnode,14,playerid+100) == 0){
        printf("0 %d",fromnode);
    }
    printf("1 %d",fromnode);
    printf("Time: %d",GetTickCount()-start);
    return 1;
}

但它不斷進行下去,CalculatePath調用靜態單元格AMX_NATIVE_CALL n_CalculatePath(AMX * amx,cell * params)

這有點令人驚訝。 有人看到錯誤嗎?

如果您需要完整的源代碼,請訪問:

http://gpb.googlecode.com/files/RouteConnector_174alpha.zip

額外信息:PLUGIN_EXPORT bool PLUGIN_CALL僅在啟動時執行加載。

靜態單元格AMX_NATIVE_CALLs僅在從虛擬機調用時執行

ProcessTick()在應用程序的每個進程滴答結束后都會執行,它在完成自己的工作后會在擴展程序中調用它。

到目前為止,我僅在Windows上測試了代碼,但在Linux上確實可以很好地編譯。

編輯:刪除了linux代碼以縮短發布時間。

根據我的見解,您的第一個代碼段僅基於某些條件來解鎖互斥鎖,即在偽代碼中,它就像:

mutex.lock ():
if some_unrelated_thing:
    mutex.unlock ()

據我了解您的代碼,原則上,第一個代碼段可以鎖定然后再解鎖。

另一個潛在的問題是您的代碼最終是不安全的異常。 您真的能夠保證鎖定/解鎖操作之間不會發生異常嗎? 因為如果曾經拋出任何未捕獲的異常,您將陷入描述的僵局。 我建議在這里使用某種RAII。

編輯:

未經測試的RAII執行鎖定/解鎖方式:

struct Lock
{
  MUTEX&  mutex;
  bool    locked;

  Lock (MUTEX& mutex)
    : mutex (mutex),
      locked (false)
  { }

  ~Lock ()
  { release (); }

  bool acquire (int timeout = -1)
  {
    if (!locked && WaitForSingleObject (mutex, timeout) == WAIT_OBJECT_0)
      locked = true;
    return locked;
  }

  int release ()
  {
    if (locked)
      locked = ReleaseMutex (mutex);
    return !locked;
  }
};

用法可能是這樣的:

{
  Lock  q (mutex_q);
  if (q.acquire (5)) {
      if (!QueueVector.empty ()) {
          q.release ();
          ...
      }
  }
}

請注意,無論您是否明確地執行此操作,無論~Lock范圍塊是正常退出還是由於未捕獲的異常,〜Lock都會始終釋放互斥鎖。

我不確定這是否是預期的行為,但是在以下代碼中:

void Thread::BackgroundCalculator( void *unused ){
while( true ){
    if(MUTEX_LOCK(&mutex_q, 5) == 1){
        if(!QueueVector.empty()){
            //cut
            MUTEX_UNLOCK(&mutex_q);
            //cut
            while(MUTEX_LOCK(&mutex_p,90000) != 1){}
            //cut
            MUTEX_UNLOCK(&mutex_p);
        }
    }
    SLEEP(25);
}

如果QueueVector.empty為true,則永遠不會解鎖mutex_q

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM