我有一个问题,我的功能之一无法获取我使用的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始终都会释放互斥锁,无论范围块是正常退出还是由于未捕获的异常而退出。

关于c++ - 互斥锁无法获取锁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9523532/

10-12 22:29