繁体   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