線程競爭問題


前言:   線程之間資源共享,所以不存在通信問題,但是會有很強烈的競爭問題,解決線程之間的競爭問題有以下幾種方法:

注:加鎖不要太大,也盡量不要太多,否則會影響效率,讀寫鎖結束最好放棄cpu調度

1.互斥量

  功能:保證同一時間只有一個線程可以對共享資源進行操作,但是不保證同步

步驟:

  1.1初始化互斥量:(2中方法,,一般常用靜態,靜態初始化用完后不需要刪除)    

   動態初始化:

      static  pthread_mutex_t     mm;

      prhread_mutex_init(&mm,NULL);

   靜態初始化:

      static  pthread_mutex_t    mm=PTHREAD_MUTEX_INITIALIZER;

  1.2 加/解鎖操作

             pthread_mutex_lock(&mm);//加鎖操作,未獲得鎖的線程則阻塞等待

     pthread_mutex_trylock(&mm)//加鎖操作,未獲得鎖的線程則非0返回,繼續執行其他                   非競爭任務

     pthread_mutex_unlock(&mm)//解鎖操作,解鎖操作不會出錯,即使沒有鎖也可以解鎖

  1.3  銷毀互斥量(鎖)

        pthread_mutex_destroy(&mm)//   靜態申請的不用銷毀

2.讀寫鎖  :讀共享    寫獨占

  功能:有時多個線程需要對同個資源進行讀寫操作時,可能會數據丟失等問題,如在寫的時      候發生了讀事件,而讀寫鎖可以有效保證  讀共享,寫獨占,主要用於既有讀,又有      寫,且讀的數量遠大於寫

  優點:能夠實現線程的高並發,但是線程的調度還不夠精准(盲目調度)

  注意:每個線程執行完后應該放棄自己的時間片,這樣可以解決線程飢餓問題

       sched_yield()       //放棄cpu調度  

  步驟:

  2.1   初始化讀寫鎖(只能動態初始化)

      static   pthread_rwlock_t       rw;//聲明一個全局鎖變量

      pthread_rwlock_init(&rw,NULL)//初始化鎖

  2.2   加/解鎖

     pthread_rwlock_wrlock(&rw);   //加一把寫鎖,若加鎖失敗則阻塞在此

     pthread_rwlock_trywrlock(&rw);   //加寫鎖,若加鎖失敗則立即返回非0值執行其他工作

     pthread_rwlock_rdlock(&rw);    //加一把讀鎖,失敗阻塞

     pthread_rwlock_tryrdlock(&rw);  //加讀鎖,失敗非阻塞

     pthread_rwlock_unlock(&rw); //解鎖(不分類型且不會失敗)

  2.3    銷毀鎖

      pthread_rwlock_ destroy(&rw); 

3.條件變量  

  功能:可以更好的協調多個線程工作,使cpu不會盲目調度,需要執行的線程收到信號后則執行,收不到信號的則睡眠等待信號。   通常需要合互斥量配合使用。互斥量保證同一時間只能有一個線程工作,條件變量能指定某個線程工作

  1初始化條件變量:(2種初始化方法,一般常用靜態)

    1.靜態初始化條件變量

      pthread_cond_t   ok=PTHREAD_COND_INITIALIZER;//申請一個變量名為ok的條件變量

           1.2 動態初始化條件變量:  

        pthread_cond_t   ok;

      pthread_cond_init(&ok,NULL);

  2.步驟:

  1.對競爭部分加互斥鎖   pthread_mutex_lock(&mm);

  2.用while循環判斷標志位,保證線程是收到信號后被喚醒的

     while(flag!=0)      {pthread_cond_wait(&no_ok,&mm); }

      ***********操作函數部分***********

  3.更改標志位  :flag

  4.解鎖    pthread_mutex_unlock(&mm); 

  5.發送信號:pthread_cond_signal()  或  pthread_cond_broadcast()

  無論哪種等待方式,都必須和一個互斥鎖配合,以防止多個線程同時請求                                                                          pthread_cond_wait((pthread_cond_timedwait(),下同)的競爭條件(Race   Condition),且在調用 pthread_cond_wait()前必須由本線程加鎖(pthread_mutex_lock()),而在更新條件等待隊列以前,mutex保持鎖 定狀態,並在線程掛起進入等待前解鎖。在條件滿足從而離開pthread_cond_wait()之前,mutex將被重新加鎖,以與進入 pthread_cond_wait()前的加鎖動作對應。   執行pthread_cond_wait()時自動解鎖互斥量(如同執行了 pthread_unlock_mutex),並等待條件變量觸發。這時線程掛起,不占用 CPU 時間,直到條件變量被觸發。

因此,全過程可以描述為:

 

(1)pthread_mutex_lock()上鎖,

 

(2)pthread_cond_wait()等待,等待過程分解為為:解鎖--條件滿足--加鎖

 

(3)pthread_mutex_unlock()解鎖。  
激發條件有兩種形式,pthread_cond_signal()激活一個等待該條件的線程,存在多個等待線程時按入隊順序激活其中一個;而pthread_cond_broadcast()則激活所有等待線程。 兩者 如果沒有等待的線程,則什么也不做。

 

   while(1)
    {
        pthread_mutex_lock(&mm);//首先加一把互斥鎖,保證只有一個線程可以搶到鎖,防止競爭
        while(flag!=0)  //加個循環防止_wait()被意外喚醒,
        {
           pthread_cond_wait(&no_ok,&mm);//等待喚醒信號,進入等待且原子性釋放鎖,收到信號並醒來,且需要持有鎖,若加                  鎖失敗則等待
        }
        printf("input>");
        fgets(buf,4096,stdin);
        flag=1;
        pthread_mutex_unlock(&mm);  //釋放鎖
        pthread_cond_signal(&ok);    //發送信號
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM