先看代码
#include <iostream> #include <pthread.h> #include <string.h> using namespace std; static pthread_mutex_t m_cMutex = PTHREAD_MUTEX_INITIALIZER; static int __number = 0; static pthread_t __thread_id = 0; void * timeout_monitor(void * args) { cout << "\n==[NOTIFICATION_FILE]==> ==== ********timeout_monitor begin ******** ========" << endl; sleep(5); pthread_mutex_lock(&m_cMutex); __number++; cout << "\n ==== ********thread __number ******** ========" << __number << endl; pthread_mutex_unlock(&m_cMutex); cout << "\n==[NOTIFICATION_FILE]==> ==== ********timeout_monitor end ******** ========" << endl; } void start_daemon_thread() { cout << "\n==[NOTIFICATION_FILE]==> ==== ********before __thread_id = %lu******** ========" << __thread_id <<endl; if(__thread_id <= 0) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&__thread_id,NULL,timeout_monitor,NULL); } cout << "\n==[NOTIFICATION_FILE]==> ==== ********after __thread_id = %lu******** ========" << __thread_id <<endl; } void add_number() { pthread_mutex_t m_cMutex; pthread_mutex_lock(&m_cMutex); __number++; cout << "\n ==== ********main __number ******** ========" << __number << endl; pthread_mutex_unlock(&m_cMutex); } int main() { // start a daemon thread cout << "\n ==== ********start_daemon_thread******** ========" << endl; start_daemon_thread(); add_number(); sleep(5); return 0; }
造成死锁的原因,是因为m_cMutex定义了两边,一个是静态变量,一个临时变量,导致程序死锁,程序的执行结果如下:
==== ********start_daemon_thread******** ======== ==[NOTIFICATION_FILE]==> ==== ********before __thread_id = %lu******** ========0 ==[NOTIFICATION_FILE]==> ==== ********after __thread_id = %lu******** ========140230716638976 ==[NOTIFICATION_FILE]==> ==== ********timeout_monitor begin ******** ======== ==== ********thread __number ******** ========1 ==[NOTIFICATION_FILE]==> ==== ********timeout_monitor end ******** ========
此时程序的堆栈信息如下:
(gdb) where #0 0x00007ffff78cb89c in __lll_lock_wait () from /lib/x86_64-linux-gnu/libpthread.so.0 #1 0x00007ffff78c7065 in _L_lock_858 () from /lib/x86_64-linux-gnu/libpthread.so.0 #2 0x00007ffff78c6eba in pthread_mutex_lock () from /lib/x86_64-linux-gnu/libpthread.so.0 #3 0x0000000000400c03 in add_number () at lock.cpp:40 #4 0x0000000000400c8f in main () at lock.cpp:53
如果在add_number()方法前面增加一个sleep(5),此时运行的结果又会不一样,改动后的代码如下:
#include <iostream> #include <pthread.h> #include <string.h> using namespace std; static pthread_mutex_t m_cMutex = PTHREAD_MUTEX_INITIALIZER; static int __number = 0; static pthread_t __thread_id = 0; void * timeout_monitor(void * args) { cout << "\n==[NOTIFICATION_FILE]==> ==== ********timeout_monitor begin ******** ========" << endl; // sleep(5); pthread_mutex_lock(&m_cMutex); __number++; cout << "\n ==== ********thread __number ******** ========" << __number << endl; pthread_mutex_unlock(&m_cMutex); cout << "\n==[NOTIFICATION_FILE]==> ==== ********timeout_monitor end ******** ========" << endl; } void start_daemon_thread() { cout << "\n==[NOTIFICATION_FILE]==> ==== ********before __thread_id = %lu******** ========" << __thread_id <<endl; if(__thread_id <= 0) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&__thread_id,NULL,timeout_monitor,NULL); } cout << "\n==[NOTIFICATION_FILE]==> ==== ********after __thread_id = %lu******** ========" << __thread_id <<endl; } void add_number() { pthread_mutex_t m_cMutex; pthread_mutex_lock(&m_cMutex); __number++; cout << "\n ==== ********main __number ******** ========" << __number << endl; pthread_mutex_unlock(&m_cMutex); } int main() { // start a daemon thread cout << "\n ==== ********start_daemon_thread******** ========" << endl; start_daemon_thread(); sleep(5); // add this the program will core add_number(); sleep(5); return 0; }
此时程序会产生core,程序core时的堆栈信息如下:
Starting program: /home/mengpl/workspace/practices/basic/lock [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". ==== ********start_daemon_thread******** ======== ==[NOTIFICATION_FILE]==> ==== ********before __thread_id = %lu******** ========0 [New Thread 0x7ffff6fef700 (LWP 3202)] ==[NOTIFICATION_FILE]==> ==== ********after __thread_id = %lu******** ========140737337292544 ==[NOTIFICATION_FILE]==> ==== ********timeout_monitor begin ******** ======== ==== ********thread __number ******** ========1 ==[NOTIFICATION_FILE]==> ==== ********timeout_monitor end ******** ======== [Thread 0x7ffff6fef700 (LWP 3202) exited] lock: pthread_mutex_lock.c:62: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed. Program received signal SIGABRT, Aborted. 0x00007ffff7536445 in raise () from /lib/x86_64-linux-gnu/libc.so.6 (gdb) where #0 0x00007ffff7536445 in raise () from /lib/x86_64-linux-gnu/libc.so.6 #1 0x00007ffff7539bab in abort () from /lib/x86_64-linux-gnu/libc.so.6 #2 0x00007ffff752f10e in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #3 0x00007ffff752f1b2 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6 #4 0x00007ffff78c6efb in pthread_mutex_lock () from /lib/x86_64-linux-gnu/libpthread.so.0 #5 0x0000000000400c03 in add_number () at lock.cpp:40 #6 0x0000000000400c99 in main () at lock.cpp:54 (gdb)
在做一次改动,把add_number函数里面的内容,直接放到main函数里来执行,此时的效果是怎样的呢?改动后的代码如下:
#include <iostream> #include <pthread.h> #include <string.h> using namespace std; static pthread_mutex_t m_cMutex = PTHREAD_MUTEX_INITIALIZER; static int __number = 0; static pthread_t __thread_id = 0; void * timeout_monitor(void * args) { cout << "\n==[NOTIFICATION_FILE]==> ==== ********timeout_monitor begin ******** ========" << endl; // sleep(5); pthread_mutex_lock(&m_cMutex); __number++; cout << "\n ==== ********thread __number ******** ========" << __number << endl; pthread_mutex_unlock(&m_cMutex); cout << "\n==[NOTIFICATION_FILE]==> ==== ********timeout_monitor end ******** ========" << endl; } void start_daemon_thread() { cout << "\n==[NOTIFICATION_FILE]==> ==== ********before __thread_id = %lu******** ========" << __thread_id <<endl; if(__thread_id <= 0) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&__thread_id,NULL,timeout_monitor,NULL); } cout << "\n==[NOTIFICATION_FILE]==> ==== ********after __thread_id = %lu******** ========" << __thread_id <<endl; } /*void add_number() { pthread_mutex_t m_cMutex; pthread_mutex_lock(&m_cMutex); __number++; cout << "\n ==== ********main __number ******** ========" << __number << endl; pthread_mutex_unlock(&m_cMutex); }*/ int main() { // start a daemon thread cout << "\n ==== ********start_daemon_thread******** ========" << endl; start_daemon_thread(); // sleep(5); // add this the program will core // add_number(); pthread_mutex_t m_cMutex; pthread_mutex_lock(&m_cMutex); __number++; cout << "\n ==== ********main __number ******** ========" << __number << endl; pthread_mutex_unlock(&m_cMutex); sleep(5); return 0; }
此时,无论加不加sleep(5),程序都能正常执行下去,不会出现死锁,具体的原因,需要进一步分析,这里先列出这样一个现象。这个是一个小错误,下次引以为戒。