/* This is an implementation of the threads API of POSIX 1003.1-2001.*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
//equivalent to PTHREAD_MUTEX_ERRORCHECK
void* thread_function(void *args)
{
int rc;
rc = pthread_mutex_unlock( & mutex );
printf( "[thread_function] pthread_mutex_unlock rc: %d \n", rc);
return 0;
}
int main(int argc, char* argv[])
{
int rc;
pthread_t id;
pthread_mutex_lock( &mutex );
rc = pthread_create(&id, NULL, thread_function, NULL);
pthread_join(id, NULL);
printf( "[main] completed\n");
}
rc = pthread_mutex_unlock( & mutex );
- 返回rc等于1,这是预期的。
但是当我将代码更改为rc = pthread_mutex_lock( & mutex );
时 - 不会发生错误。
但是在许多Pthread API文档中提到:
“如果互斥锁类型为PTHREAD_MUTEX_ERRORCHECK,则应提供错误检查。如果某个线程试图重新锁定已锁定的互斥锁,则将返回错误。”
但它不会归还给我,问题为什么? 我唯一的猜测 - 它取决于我正在使用的PThread实现。 它也可能取决于操作系统;即相同的代码和相同版本的Pthread lib将在Linux上提供不同的结果。
有人可以澄清一下吗?
谢谢!
答案 0 :(得分:2)
当一个线程试图锁定另一个线程锁定的互斥锁时,它会阻止。这当然是重点:如果是错误就没用了。错误检查适用于线程可能尝试锁定互斥锁 已锁定的程序。这通常是由逻辑错误引起的,虽然可以使用它来模拟递归互斥锁,或者可能使用互斥锁的锁定状态作为某种内存。
答案 1 :(得分:0)
通常,当您第二次尝试在同一线程中锁定互斥锁(默认类型)时,代码已被阻止。为了防止这种阻塞情况,使用了错误检查互斥锁。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#define IN_MAIN ""
#define IN_THREAD "\t"
#define START_MAIN printf(IN_MAIN "\n-- Main Start -- \n");
#define END_MAIN printf(IN_MAIN "-- Main End -- \n\n"); \
exit(EXIT_SUCCESS);
#define ERROR_HANDLER(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void * thread_routine(void * arg)
{
printf(IN_THREAD "-- Thread Start -- \n");
int ret;
pthread_mutex_lock(&mutex);
printf(IN_THREAD " Thread acquire lock for first time \n");
ret = pthread_mutex_lock(&mutex);
if(ret)
{
switch(ret)
{
case EDEADLK:
printf(IN_THREAD " A deadlock condition was detected \n");
break;
default:
ERROR_HANDLER(ret, "pthread_mutex_lock");
}
}
sleep(1);
ret = pthread_mutex_unlock(&mutex);
printf(IN_THREAD " Thread release lock first time -- %d \n", ret);
sleep(1);
ret = pthread_mutex_unlock(&mutex);
printf(IN_THREAD " Thread release lock second time -- %d \n", ret);
printf(IN_THREAD "-- Thread End --\n");
pthread_exit(NULL);
}
int main(int argc, char ** argv)
{
START_MAIN;
pthread_t thread_id;
pthread_mutexattr_t mutex_attr;
int mutex_type, ret=0;
pthread_mutexattr_init(&mutex_attr);
ret = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
if(ret)
ERROR_HANDLER(ret, "pthread_mutexattr_settype");
pthread_mutex_init(&mutex, &mutex_attr);
pthread_create(&thread_id, NULL, thread_routine, NULL);
pthread_join(thread_id, NULL);
END_MAIN;
}
考虑上面的示例,当您执行上面的代码时,它显示“检测到死锁条件”。这是因为互斥锁的类型是错误检查。 现在注释该行
ret = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
并执行代码。您会在代码显示“首次获取线程锁定”后发现代码被阻止。
答案 2 :(得分:0)
Posix 规范中的一个错误是“默认”互斥类型的概念——它依赖于实现。意思是“默认”互斥锁的语义是任何人猜测的。令人困惑?你打赌。
如果您完全关心可移植性,我的建议是永远不要对互斥类型使用“默认”。