在同一个线程中多次锁定互斥锁

时间:2010-05-12 17:34:17

标签: c linux posix embedded-linux uclinux

我正在开发嵌入式Linux操作系统(uClinux)上的应用程序,我需要能够多次锁定互斥锁(通过同一个线程)。

我有一个mutex和mutexattr定义并初始化如下:

pthread_mutexattr_t waiting_barcode_mutexattr;
pthread_mutex_t waiting_barcode_mutex;

pthread_mutexattr_init(&waiting_barcode_mutexattr);
pthread_mutexattr_settype(&waiting_barcode_mutexattr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&waiting_barcode_mutex, &waiting_barcode_mutexattr);

但是当我试图获得两次锁定时,它会阻止第二次锁定:

pthread_mutex_lock(&waiting_barcode_mutex);
pthread_mutex_lock(&waiting_barcode_mutex);

我初始化错误还是有更好的方法来完成同样的工作?

提前致谢。

结论:

  • 显然PTHREAD_MUTEX_RECURSIVE或PTHREAD_MUTEX_RECURSIVE_NP不起作用,因此我无法创建可重入的互斥锁。
  • try_lock也不好。如果可以,它获取锁定,如果无法获取锁定则返回错误。不幸的是,错误只是告诉我互斥锁已经在使用中,我不知道当前线程是否已经拥有锁。
  • 如果当前线程有锁,则pthread_mutex_lock可以返回错误但是我需要创建PTHREAD_MUTEX_ERRORCHECK类型的互斥锁,我也不能创建一个。

5 个答案:

答案 0 :(得分:10)

这不是你想要的吗?

第一个调用获取锁定,第二个调用将阻塞,直到释放第一个锁定(pthread_mutex_unlock)。锁就是这样做的。

来自文档:

“如果互斥锁已被锁定,则调用线程将阻塞,直到互斥锁变为可用。”

也许你想要pthread_mutex_trylock?除非我们知道你想要完成什么,否则很难说。

<强> CORRECTION:

我没有看到你正在设置PTHREAD_MUTEX_RECURSIVE ....让我再考虑一下。

思考之后:

从围绕谷歌代码搜索,看起来PTHREAD_MUTEX_RECURSIVE并未在所有库中实现。您可以尝试PTHREAD_MUTEX_RECURSIVE_NP,或者您可能已经做了一些想要解决这个问题的事情。

答案 1 :(得分:2)

听起来pthread互斥锁不是可重入的。您可以使用一个标志来解决此问题,该标志指示您的线程是否已锁定互斥锁:

bool haveLock = false;// thread variable
pthread_mutex_t waiting_barcode_mutex; // also thread var

mylock()
{
   if( haveLock ) return; // no need to lock twice
   pthread_mutex_lock(&waiting_barcode_mutex);
   haveLock = true;
}

myunlock()
{
   haveLock = false;
   pthread_mutex_unlock(&waiting_barcode_mutex); // or whatever the unlock call is
}

答案 2 :(得分:1)

以下是在我的Dell m6300上的UBUNTU 12.04 LTS上测试的工作代码:

  pthread_mutex_t mutex;
  pthread_mutexattr_t attr;
  int rc = pthread_mutexattr_init(&attr);
    if (rc != 0)
        throw (L"pthread_mutexattr_init returns " + rc);
    rc = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE_NP);
    if (rc != 0)
        throw (L"pthread_mutexattr_settype returns " + rc);
    rc = pthread_mutex_init (&mutex, &attr);
    if (rc != 0)
        throw (L"pthread_mutex_init returns " + rc);
    rc = pthread_mutexattr_destroy(&attr);
    if (rc != 0)
        throw (L"pthread_mutexattr_destroy returns " + rc);

   //first lock
   rc = pthread_mutex_lock(&mutex);
    if (rc != 0)
        throw (L"pthread_mutex_lock returns " + rc);
   //second lock
   rc = pthread_mutex_lock(&mutex);
    if (rc != 0)
        throw (L"pthread_mutex_lock returns " + rc);

不要忘记在获取互斥锁时多次释放互斥锁。

答案 3 :(得分:1)

  

下面的代码显示,在调用pthread上的解锁之前,将关键部分锁定两次或三次或N次没有问题。您可以在解锁前连续在同一个线程上执行多个锁定而不用担心,但请注意,这不是一个优秀的程序员的做法。正确的方法是调用lock(),让线程执行临界区并调用unlock(),这样其他线程就可以在锁定和解锁之间执行相同的代码(称为临界区)。下面的代码可以防止程序员在pthread上使用ATTRIBUTES的意外事件。

     

继续阅读!

// Example program using a thread locking multiple times sequentially before unlocking
#include <iostream>

using namespace std;

pthread_mutexattr_t     _attr;
pthread_mutex_t         _mutex;

///
/// Initialize mutex with error return locking mechanism (does not block
/// its own thread if multiple locks occurs.
///
void InitMutex()
{
   // Initialize mutex
   int ret=0;
   ret = pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_ERRORCHECK_NP);   // PTHREAD_MUTEX_ERRORCHECK_NP avoids double locking on same thread.
   if(ret != 0)
   {
      printf("Mutex attribute not initialized!!\n");
   }
   ret = pthread_mutex_init(&_mutex, &_attr);
   if(ret != 0)
   {
      printf("Mutex not initialized!!\n");
   }
}

///
/// Locks the critical section
///
int lock_me()
{
   return pthread_mutex_lock(&_mutex);
}

///
/// Unlocks the critical section
///
int unlock_me()
{
   return pthread_mutex_unlock(&_mutex);
}

int main()
{
  InitMutex(); // Very important
  int ret = 0;

  ret = lock_me();    // return value of 0 - OK
  cout << "First lock returns: "<< ret<< endl;
  ret = lock_me();    // returns a value like 35 - ERROR, but ignores locking again
  cout << "Second lock returns: "<< ret<< endl;

  // Do something in this critical section. No other thread can execute this at this time before unlock. Other threads (if any) wait at lock() waiting for main function to unlock() first.

  ret = unlock_me();  // unlocks the critical section. All is OK
  cout << "First unlock returns: "<< ret<< endl;
  ret = unlock_me();  // returns error value of 1, nothing to lock
  cout << "Second unlock returns: "<< ret<< endl;
  ret = unlock_me();  // same as above, nothing to do. Ignore and move on!
  cout << "Third unlock returns: "<< ret << endl;

  // The main() thread will never have a race condition ;) All iz well!!

  pthread_mutexattr_destroy(&_attr);    // clean up the mutex attribute
  pthread_mutex_destroy(&_mutex);       // clean up the mutex itself

}

<强> 输出:

  

第一次锁定返回:0

     

第二次锁定返回:35

     

首先解锁返回:0

     

第二次解锁返回:1

     

第三次解锁返回:1

答案 4 :(得分:1)

(刚刚意识到我没有将这个问题标记为已回答)

取自问题中的结论:

  • 显然PTHREAD_MUTEX_RECURSIVE或PTHREAD_MUTEX_RECURSIVE_NP不起作用,因此我无法创建可重入的互斥锁。
  • try_lock也不好。如果可以,它获取锁定,如果无法获取锁定则返回错误。不幸的是,错误只是告诉我互斥锁已经在使用中,我不知道当前线程是否已经拥有锁。
  • 如果当前线程有锁,则pthread_mutex_lock可以返回错误但是我需要创建PTHREAD_MUTEX_ERRORCHECK类型的互斥锁,我也不能创建一个。