我正在开发嵌入式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);
我初始化错误还是有更好的方法来完成同样的工作?
提前致谢。
答案 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)
(刚刚意识到我没有将这个问题标记为已回答)
取自问题中的结论: