一个多线程死锁问题的模拟

  先看代码

 #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),程序都能正常执行下去,不会出现死锁,具体的原因,需要进一步分析,这里先列出这样一个现象。这个是一个小错误,下次引以为戒。

  

  

转载于:https://www.cnblogs.com/xiaomengaliang/p/3638486.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值