首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >互斥锁无法获得锁

互斥锁无法获得锁
EN

Stack Overflow用户
提问于 2012-03-01 20:29:49
回答 2查看 3.3K关注 0票数 0

我有一个问题,我的一个函数不能对我使用的两个互斥锁中的一个进行锁定。我在VC++2010中做了一个基本的调试,设置了一些断点,而且如果获得锁的任何地方,它都会被解锁。

使用互斥的代码如下:

代码语言:javascript
复制
#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);
    }
}

那么还有其他的地方:

代码语言:javascript
复制
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;
}

代码语言:javascript
复制
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;
}

init:

代码语言:javascript
复制
PLUGIN_EXPORT bool PLUGIN_CALL Load( void **ppData ) {
    MUTEX_INIT(&mutex_q);
    MUTEX_INIT(&mutex_p);
    START_THREAD( Thread::BackgroundCalculator, 0);
    return true;
}

一些变量和函数:

代码语言:javascript
复制
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;

并界定:

代码语言:javascript
复制
#   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 ) ); }

线程头文件:

代码语言:javascript
复制
#ifndef __THREAD_H
#define __THREAD_H

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

};

#endif

我似乎找不到问题了。调试后,我想通过以下代码“强制”查询锁(从典当抽象机器):

代码语言:javascript
复制
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代码以缩短post。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-03-04 17:47:21

根据我所看到的,您的第一个代码段只在某些条件下解锁互斥锁,例如,在伪代码中,它类似于:

代码语言:javascript
复制
mutex.lock ():
if some_unrelated_thing:
    mutex.unlock ()

正如我理解您的代码一样,通过这种方式,第一个代码段原则上可以锁定,然后永远不会解锁。

另一个潜在的问题是,您的代码最终是异常-不安全。您真的能够保证锁/解锁操作之间不会发生异常吗?因为如果有任何异常被抛出,您就会陷入所描述的死锁。我建议在这里使用某种RAII。

编辑:

未经测试的RAII执行锁/解锁的方式:

代码语言:javascript
复制
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;
  }
};

用法可以是这样的:

代码语言:javascript
复制
{
  Lock  q (mutex_q);
  if (q.acquire (5)) {
      if (!QueueVector.empty ()) {
          q.release ();
          ...
      }
  }
}

请注意,~Lock总是以这种方式释放互斥对象,无论您是否显式地这样做,作用域块是否正常退出,还是由于一个不明确的异常。

票数 2
EN

Stack Overflow用户

发布于 2012-03-04 17:50:50

我不确定这是否是有意的行为,但在下面的代码中:

代码语言:javascript
复制
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为真,则永远不会解锁mutex_q

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9523532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档