(原)聊一聊程序死锁的问题

今天在项目的过程中,程序运行一段时间,http服务就没办法响应了。通过日志排查,发现最后是因为在http响应的程序中,程序一直卡死再lock这个地方。通过半天思考自己的代码,貌似一直没想通自己这个地方为什么会死锁,貌似我程序没有出现啊?我都是在同一个对象同一个函数加锁和解锁成对出现的啊?不可能出现这个函数没解锁又上锁的问题啊?
上锁和解锁的相关代码如下:
 1 bool WorkQueue::do_add_work(WorkBase* work)
 2 {
 3 //    ELogPrint("add lock");
 4     if (0 != pthread_mutex_lock(&m_queue_lock)) {
 5         ELogPrint("lock failed");
 6 //        delete work;
 7 //        work = NULL;
 8         return false;
 9     }
10     
11     while (m_queue_size >= MAX_WORK_NUMBER){
12         DLogPrint("waiting producer cond:queue size:%d",m_queue_size);
13         pthread_cond_wait(&m_producer_cond, &m_queue_lock); // when thread wake up, the mutext is locked already
14         DLogPrint("receive producer cond,queue size:%d",m_queue_size);
15     }
16     
17     m_work_queue.push_back(work);
18     m_queue_size++;
19 //    //这里需要排重,防止重复
20 //    //遍历
21 //    bool find=false;
22 //    list<WorkBase*>::iterator iter=m_work_queue.begin();
23 //    for(;iter!=m_work_queue.end();){
24 //        WorkBase*pW=*iter;
25 //        if(pW==work){//如果相等
26 //            find=true;
27 //        }
28 //        else{
29 //            iter++;
30 //        }
31 //    }
32 //    if(!find){
33 //        m_work_queue.push_back(work);
34 //        m_queue_size++;
35 //    }
36 //    DLogPrint("add broadcast or signal worker cond");
37     /* wake up a worker thread */
38     pthread_cond_signal(&m_worker_cond);
39 //    pthread_cond_broadcast(&m_worker_cond);
40 
41     pthread_mutex_unlock(&m_queue_lock);
42 //     DLogPrint("add unlock");
43     return true;    
44 }
45 
46 WorkBase* WorkQueue::get_work()
47 {
48     WorkBase* work = NULL;
49     if (0 != pthread_mutex_lock(&m_queue_lock)){
50         ELogPrint("get lock failed");
51         return work;
52     }
53     
54     while (m_queue_size == 0){
55 //        DLogPrint("waiting worker cond:queue size:%d",m_queue_size);
56         pthread_cond_wait(&m_worker_cond, &m_queue_lock);   // when thread wake up, the mutext is locked already
57 //        DLogPrint("receive worker cond,queue size:%d",m_queue_size);
58     }
59     
60 //    work = m_work_queue.front();
61 //    m_work_queue.pop();
62     //取第一个元素
63     work = m_work_queue.front();
64     m_work_queue.pop_front();
65     m_queue_size--;    
66 
67 //    DLogPrint("get broadcast or signal producer cond");
68     /* wake up a sleeping producer, maybe there is one */
69     pthread_cond_signal(&m_producer_cond);
70 //    pthread_cond_broadcast(&m_producer_cond);
71 
72     pthread_mutex_unlock(&m_queue_lock); 
73 //    DLogPrint("get unlock");
74     return work;
75 }

之前都不会出现死锁的情况?无法现在是加了红色的那段代码啊,为什么就这么容易出现死锁呢?

后面想了一下,我们会在线程池和状态机中不断的添加任务和做任务,同时在处理外部信号的时候,因为我们的程序在http响应的过程中会去根据消息中的id找到这个task对象,然后调用这个task的add_task函数,将这个task添加到线程池中,所以如果在http处理的过程中,出现了超时,http_client就会重发消息,这样的话,在http的处理底层线程中,用了一个新的线程去处理,同时获取到和前面一个没响应的消息,获取的task对象是同一个,这样如果前面一次的add_task挂在了lock函数的位置,这次再来lock的话,是不是就会出现死锁的问题呢?

 

 

原文出处:https://www.cnblogs.com/lihaiping/p/10457744.html

 

 

 

 

 
posted @ 2019-03-01 17:30  lihaiping  阅读(346)  评论(0编辑  收藏  举报