Linux 線程同步—條件變數

來源:互聯網
上載者:User

 

1. 相關函數                                                                                         
       #include <pthread.h>
       pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
       int    pthread_cond_init(pthread_cond_t    *cond,    pthread_condattr_t
       *cond_attr);
       int pthread_cond_signal(pthread_cond_t *cond);
       int pthread_cond_broadcast(pthread_cond_t *cond);
       int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
       int   pthread_cond_timedwait(pthread_cond_t   *cond,    pthread_mutex_t
       *mutex, const struct timespec *abstime);
       int pthread_cond_destroy(pthread_cond_t *cond);
                                                                                          
2. 說明
    條件變數是一種同步機制,允許線程掛起,直到共用資料上的某些條件得到滿足。條件變數上的基本操作有:觸發條件(當條件變為 true 時);等待條件,掛起線程直到其他線程觸發條件。
    條件變數要和互斥量相連接,以避免出現條件競爭--一個線程預備等待一個條件變數,當它在真正進入等待之前,另一個線程恰好觸發了該條件。
    pthread_cond_init 使用 cond_attr 指定的屬性初始化條件變數 cond,當 cond_attr 為 NULL 時,使用預設的屬性。LinuxThreads 實現條件變數不支援屬性,因此 cond_attr 參數實際被忽略。
    pthread_cond_t 類型的變數也可以用 PTHREAD_COND_INITIALIZER 常量進行靜態初始化。                                                                                          
    pthread_cond_signal 使在條件變數上等待的線程中的一個線程重新開始。如果沒有等待的線程,則什麼也不做。如果有多個線程在等待該條件,只有一個能重啟動,但不能指定哪一個。
    pthread_cond_broadcast 重啟動等待該條件變數的所有線程。如果沒有等待的線程,則什麼也不做。
    pthread_cond_wait 自動解鎖互斥量(如同執行了 pthread_unlock_mutex),並等待條件變數觸發。這時線程掛起,不佔用 CPU 時間,直到條件變數被觸發。在調用 pthread_cond_wait 之前,應用程式必須加鎖互斥量。pthread_cond_wait 函數返回前,自動重新對互斥量加鎖(如同執行了 pthread_lock_mutex)。
    互斥量的解鎖和在條件變數上掛起都是自動進行的。因此,在條件變數被觸發前,如果所有的線程都要對互斥量加鎖,這種機制可保證線上程加鎖互斥量和進入等待條件變數期間,條件變數不被觸發。
    pthread_cond_timedwait 和 pthread_cond_wait 一樣,自動解鎖互斥量及等待條件變數,但它還限定了等待時間。如果在 abstime 指定的時間內 cond 未觸發,互斥量 mutex 被重新加鎖,且 pthread_cond_timedwait 返回錯誤 ETIMEDOUT。abstime 參數指定一個絕對時間,時間原點與 time 和 gettimeofday 相同:abstime = 0 表示 1970 年 1 月 1 日 00:00:00 GMT。
    pthread_cond_destroy 銷毀一個條件變數,釋放它擁有的資源。進入 pthread_cond_destroy 之前,必須沒有在該條件變數上等待的線程。在 LinuxThreads 的實現中,條件變數不連接資源,除檢查有沒有等待的線程外,pthread_cond_destroy 實際上什麼也不做。
3. 取消                                                                                          
    pthread_cond_wait 和 pthread_cond_timedwait 是取消點。如果一個線程在這些函數上掛起時被取消,線程立即繼續執行,然後再次對 pthread_cond_wait 和 pthread_cond_timedwait 在 mutex 參數加鎖,最後執行取消。因此,當調用清除處理常式時,可確保,mutex 是加鎖的。
4. 非同步訊號安全(Async-signal Safety)                                                                                          
    條件變數函數不是非同步訊號安全的,不應當在訊號處理常式中進行調用。特別要注意,如果在訊號處理常式中調用 pthread_cond_signal 或 pthread_cond_boardcast 函數,可能導致調用線程死結。
                                                                                          
5. 傳回值
    在執行成功時,所有條件變數函數都返回 0,錯誤時返回非零的錯誤碼。
6. 錯誤碼
    pthread_cond_init,   pthread_cond_signal,  pthread_cond_broadcast, 和 pthread_cond_wait 從不返回錯誤碼。
    pthread_cond_timedwait 函數出錯時返回下列錯誤碼:
        ETIMEDOUT   abstime 指定的時間逾時時,條件變數未觸發
        EINTR       pthread_cond_timedwait 被觸發中斷
    pthread_cond_destroy 函數出錯時返回下列錯誤碼:
        EBUSY       某些線程正在等待該條件變數
7. 舉例                                                                                     
    設有兩個共用的變數 x 和 y,通過互斥量 mut 保護,當 x > y 時,條件變數 cond 被觸發。
             int x,y;
             int x,y;
             pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
             pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
                                                                                          
    等待直到 x > y 的執行流程:
              pthread_mutex_lock(&mut);
              while (x <= y) {
                      pthread_cond_wait(&cond, &mut);
              }
              /* 對 x、y 進行操作 */
              pthread_mutex_unlock(&mut);
                                                                                          
     對 x 和 y 的修改可能導致 x > y,應當觸發條件變數:                                                                                          
              pthread_mutex_lock(&mut);
              /* 修改 x、y */
              if (x > y) pthread_cond_broadcast(&cond);
              pthread_mutex_unlock(&mut);
                                                                                          
    如果能夠確定最多隻有一個等待線程需要被喚醒(例如,如果只有兩個線程通過 x、y 通訊),則使用 pthread_cond_signal 比 pthread_cond_broadcast 效率稍高一些。如果不能確定,應當用 pthread_cond_broadcast。
    要等待在 5 秒內 x > y,這樣處理:
                                                                                          
              struct timeval now;
              struct timespec timeout;
              int retcode;
                                                                                          
              pthread_mutex_lock(&mut);
              gettimeofday(&now);
              timeout.tv_sec = now.tv_sec + 5;
              timeout.tv_nsec = now.tv_usec * 1000;
              retcode = 0;
              while (x <= y && retcode != ETIMEDOUT) {
                      retcode = pthread_cond_timedwait(&cond, &mut, &timeout);
              }
              if (retcode == ETIMEDOUT) {
                      /* 發生逾時 */
              } else {
                      /* 操作 x 和  y */
              }
              pthread_mutex_unlock(&mut);

 

 

 原文地址 http://blog.csdn.net/hiflower/archive/2008/03/18/2195350.aspx

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.