九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
使用pthread

使用上pthread_cond_t遇到的死鎖問題 

最近在一個項目中使用pthread_cond_t的時遇到一個死鎖的問題,特記錄分享一下。這個問題的使用場景很簡單,客戶端程序起兩個線程,一個線程發(fā)送數(shù)據(jù)給服務器,另一個線程接收服務器的返回。發(fā)送線程向服務器發(fā)送一個數(shù)據(jù)報,然后等待服務器返回(用pthread_cond_t等待),然后繼續(xù)發(fā)送下一個數(shù)據(jù)包……,如此循環(huán)下去。發(fā)送代碼抽取出來的邏輯像下面這樣:


static void* thread_fun_send(void* nouse)

{

    intsend_index = 0;

    while(1)

    {

        //模擬發(fā)送數(shù)據(jù)的socket系統(tǒng)調(diào)用

        printf("send%d\n",send_index++);

 

        //通知接收線程可以接收數(shù)據(jù)

        pthread_mutex_lock(&mutex_send);

        pthread_cond_signal(&cond_send);

        pthread_mutex_unlock(&mutex_send);

 

        //等待收到數(shù)據(jù)的pthread_cond_t

        pthread_mutex_lock(&mutex_recv);

       pthread_cond_wait(&cond_recv, &mutex_recv);

       pthread_mutex_unlock(&mutex_recv);

   }  

}


接收線程等待服務器的返回,收到服務器返回后給發(fā)送線程發(fā)信號(用pthread_cond_t發(fā)信號),然后繼續(xù)等待接收服務器下一個返回……,如此循環(huán)下去。接收代碼抽取出來的邏輯像下面這樣:

static void* thread_fun_recv(void* nouse)

{

   int recv_index = 0;

   while(1)

   {  

        //等待收到數(shù)據(jù)的pthread_cond_t,模擬阻塞的socket

       pthread_mutex_lock(&mutex_send);

       pthread_cond_wait(&cond_send, &mutex_send);

       pthread_mutex_unlock(&mutex_send);

 

        //模擬接收數(shù)據(jù)的socket系統(tǒng)調(diào)用

       printf("recv %d\n",recv_index++);

 

        //通知發(fā)送線程數(shù)據(jù)已經(jīng)收到

       pthread_mutex_lock(&mutex_recv);

       pthread_cond_signal(&cond_recv);

        pthread_mutex_unlock(&mutex_recv);

   }  

}

就這么一個簡單的應用場景,看起來好像是很合乎邏輯的,但在實際的運行中會出現(xiàn)死鎖的問題。經(jīng)過綜合分析后發(fā)現(xiàn)其實是在理解pthread_cond_t上不準確了,一開始會認為它和windows中的Event是一樣的,只是調(diào)用的API函數(shù)名不同而已,其實它們是不同的。且不說自動重置這個功能,在信號的處理上它們也是完全不同的。在Windows中,當Event被置為有信號時,內(nèi)核會檢查有沒有在等待這個信號的線程,如果有則喚醒它,如果沒有信號會保存起來,下一個等待此信號的線程進來時會直接獲得信號而繼續(xù)運行;但在Linux, 如果pthread_cond_t被置為有信號時,內(nèi)核也是會檢查有沒有在等待這個信號的線程,如果有則喚醒它,但如果沒有等待的線程內(nèi)核則不會保存這個信號(好像這個信號被丟掉了一樣),下一個等待信號的線程進來時是不會獲得信號而只會進入睡眠的,只有在睡眠后下一次pthread_cond_t被置為有信號時,這個線程才會被喚醒。


搞清楚了pthread_cond_tEvent的邏輯之后,對于上面這個客戶端的業(yè)務邏輯,用最小的改動方式就是把使用pthread_cond_t改為sem_t問題就解決了。

附:測試代碼,用下面命令即可編譯
gcc -o test_cond test_cond.c -pthread

點擊(此處)折疊或打開

  1. // File Name: test_cond.c
  2. // Purpose: For Linux pthread_cond_t test
  3. #include <pthread.h>
  4. #include <unistd.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>

  7. static pthread_cond_t cond_send;
  8. static pthread_mutex_t mutex_send;

  9. static pthread_cond_t cond_recv;
  10. static pthread_mutex_t mutex_recv;

  11. static pthread_t thread_send;
  12. static pthread_t thread_recv;

  13. static void* thread_fun_send(void* nouse)
  14. {
  15.     int send_index = 0;

  16.     //wait a moment for recv thread starting up
  17.     sleep(1);

  18.     while(1)
  19.     {
  20.         printf("send %d\n",send_index++);

  21.         pthread_mutex_lock(&mutex_send);
  22.         pthread_cond_signal(&cond_send);
  23.         pthread_mutex_unlock(&mutex_send);

  24.         pthread_mutex_lock(&mutex_recv);
  25.         pthread_cond_wait(&cond_recv, &mutex_recv);
  26.         pthread_mutex_unlock(&mutex_recv);

  27.     }
  28. }

  29. static void* thread_fun_recv(void* nouse)
  30. {
  31.     int recv_index = 0;
  32.     while(1)
  33.     {
  34.         pthread_mutex_lock(&mutex_send);
  35.         pthread_cond_wait(&cond_send, &mutex_send);
  36.         pthread_mutex_unlock(&mutex_send);

  37.         printf("recv %d\n",recv_index++);

  38.         pthread_mutex_lock(&mutex_recv);
  39.         pthread_cond_signal(&cond_recv);
  40.         pthread_mutex_unlock(&mutex_recv);
  41.     }
  42. }

  43. void init()
  44. {
  45.     pthread_mutex_init(&mutex_send, 0);
  46.     pthread_cond_init(&cond_send, 0);

  47.     pthread_mutex_init(&mutex_recv, 0);
  48.     pthread_cond_init(&cond_recv, 0);

  49.     pthread_create(&thread_send, NULL ,thread_fun_send, NULL);
  50.     pthread_create(&thread_recv, NULL ,thread_fun_recv, NULL);
  51. }

  52. void clean()
  53. {
  54.     pthread_cond_destroy(&cond_send);
  55.     pthread_mutex_destroy(&mutex_send);

  56.     pthread_cond_destroy(&cond_recv);
  57.     pthread_mutex_destroy(&mutex_recv);
  58. }


  59. void main()
  60. {
  61.     printf("Test pthread_cond_t applet\n");
  62.     
  63.     init();

  64.     while(1)
  65.     {
  66.         sleep(1);
  67.     }

  68.     clean();
  69.     return;
  70. }


 

本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
POSIX多線程實現(xiàn)生產(chǎn)者消費者模式
Linux內(nèi)核多線程-各個平臺下的多線程
200行C代碼實現(xiàn)簡單線程池 - Linux內(nèi)核編程 - 舉世無雙的學習之路
Linux之線程同步
【原創(chuàng)】技術(shù)系列之 線程(二)
淺析pthread_cond_wait
更多類似文章 >>
生活服務
熱點新聞
分享 收藏 導長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服