我一直在将一个跨平台的C++引擎移植到Android上,并注意到当调用C++时,它会莫名其妙地(而且不一致地)阻塞这个引擎已经在几个平台上运行了很多年,问题代码已经很多年没有改变了,所以我怀疑它是不是死锁或者其他错误的代码。这一定是我去Android的端口。
到目前为止,代码中有几个地方阻塞在pthread_mutex_lock上。它也不是完全可复制的。当它挂起时,LogCat中没有可疑的输出。
我像这样修改了互斥码(为简洁而编辑).实际代码检查所有返回值):
void MutexCreate( Mutex* m )
{
#ifdef WINDOWS
InitializeCriticalSection( m );
#else ANDROID
pthread_mutex_init( m, NULL );
#endif
}
void MutexDestroy( Mutex* m )
{
#ifdef WINDOWS
DeleteCriticalSection( m );
#else ANDROID
pthread_mutex_destroy( m, NULL );
#endif
}
void MutexLock( Mutex* m )
{
#ifdef WINDOWS
EnterCriticalSection( m );
#else ANDROID
pthread_mutex_lock( m );
#endif
}
void MutexUnlock( Mutex* m )
{
#ifdef WINDOWS
LeaveCriticalSection( m );
#else ANDROID
pthread_mutex_unlock( m );
#endif
}我试着修改MutexCreate,使其成为错误检查和递归互斥,但这并不重要。我甚至没有得到错误或日志输出,所以这意味着我的互斥代码只是好的,或者错误/日志没有显示。操作系统是如何通知你坏互斥的使用情况的?
引擎大量使用静态变量,包括互斥变量。我看不出是怎么回事,但这有问题吗?我对此表示怀疑,因为我修改了大量的互斥变量,以便将其分配到堆中,并且发生了相同的行为。但那可能是因为我错过了一些静态互斥。我可能是在抓吸管。
我读了几处参考资料,其中包括:
init.html
mutandis
init
发布于 2012-12-11 00:46:51
“错误检查”互斥将检查几件事情(比如试图递归地使用非递归互斥),但没有什么特别之处。
您说的是“真正的代码检查所有返回值”,因此如果任何线程调用返回一个非零值,那么您的代码可能会爆炸。(不知道为什么pthread_mutex_destroy需要两个arg;假设复制和粘贴错误。)
P线程代码在Android中被广泛使用,并且没有已知的通道,所以这个问题不太可能出现在p线程实现本身。
当前互斥的实现符合32位,所以如果将*(pthread_mutex_t* mut)打印为整数,您应该能够知道它处于什么状态(从技术上讲,它在过去的某个时刻处于什么状态)。仿生/libc/bionic/pthread.c中的定义是:
/* a mutex is implemented as a 32-bit integer holding the following fields
*
* bits: name description
* 31-16 tid owner thread's kernel id (recursive and errorcheck only)
* 15-14 type mutex type
* 13 shared process-shared flag
* 12-2 counter counter of recursive mutexes
* 1-0 state lock state (0, 1 or 2)
*/“快速”互斥对象的类型为0,并且不设置tid字段。实际上,泛型互斥体的值将为0(未持有)、1(持有)或2(持有,带有争用)。如果你曾经看到一个快速互斥的值不是其中之一,很有可能会有什么东西出现并踩在它上。
这还意味着,如果您将您的程序配置为使用递归互斥,您可以通过拔出这些位来查看哪个线程保存互斥对象(或者在trylock指示您将要停止运行时打印互斥量值,或者在挂起进程上使用gdb显示状态)。这加上ps -t的输出,将让您知道锁定互斥锁的线程是否仍然存在。
https://stackoverflow.com/questions/13755355
复制相似问题