(原)聊一聊程序死鎖的問題

今天在項目的過程當中,程序運行一段時間,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 }

以前都不會出現死鎖的狀況?沒法如今是加了紅色的那段代碼啊,爲何就這麼容易出現死鎖呢?html

後面想了一下,咱們會在線程池和狀態機中不斷的添加任務和作任務,同時在處理外部信號的時候,由於咱們的程序在http響應的過程當中會去根據消息中的id找到這個task對象,而後調用這個task的add_task函數,將這個task添加到線程池中,因此若是在http處理的過程當中,出現了超時,http_client就會重發消息,這樣的話,在http的處理底層線程中,用了一個新的線程去處理,同時獲取到和前面一個沒響應的消息,獲取的task對象是同一個,這樣若是前面一次的add_task掛在了lock函數的位置,此次再來lock的話,是否是就會出現死鎖的問題呢?函數

 

 

原文出處:https://www.cnblogs.com/lihaiping/p/10457744.htmlspa

相關文章
相關標籤/搜索