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


    今天在项目的过程中,程序运行一段时间,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

     
  • 相关阅读:
    frame和iframe区别
    idea基本
    Spring中加载xml配置文件的六种方式
    java中Map,List与Set的区别
    java集合框架
    springmvc IDEA
    springmvc 精华
    eclipse 中 git 解决冲突(重点)
    启动Tomcat报错 java.util.zip.ZipException: invalid LOC header (bad signature)
    PowerDesigner 提示 Existence of index、key、reference错误
  • 原文地址:https://www.cnblogs.com/lihaiping/p/10457744.html
Copyright © 2020-2023  润新知