日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

pthread_cond_wait().

 weicat 2010-07-13
pthread_cond_wait(). 收藏
    今天終于有點明白了,趕快記下心得!
    條件變量的結(jié)構(gòu)為pthread_cond_t,函數(shù)pthread_cond_init()被用來初始化一個條件變量。它的原型為:
  extern int pthread_cond_init __P ((pthread_cond_t *__cond,__const pthread_condattr_t *__cond_attr));
  其中cond是一個指向結(jié)構(gòu)pthread_cond_t的指針,cond_attr是一個指向結(jié)構(gòu)pthread_condattr_t的指針。結(jié)構(gòu) pthread_condattr_t是條件變量的屬性結(jié)構(gòu),和互斥鎖一樣我們可以用它來設(shè)置條件變量是進程內(nèi)可用還是進程間可用,默認值是 PTHREAD_ PROCESS_PRIVATE,即此條件變量被同一進程內(nèi)的各個線程使用。注意初始化條件變量只有未被使用時才能重新初始化或被釋放。釋放一個條件變量的函數(shù)為pthread_cond_destroy(pthread_cond_t cond)?!?/div>
    也可以靜態(tài)的初始化條件變量
     pthread_cond_t my_condition = PTHREAD_COND_INITIALIZER;
  函數(shù)pthread_cond_wait()使線程阻塞在一個條件變量上。它的函數(shù)原型為:
  extern int pthread_cond_wait __P ((pthread_cond_t *__cond,pthread_mutex_t *__mutex));
   調(diào)用這個函數(shù)時,線程解開mutex指向的鎖并被條件變量cond阻塞。線程可以被函數(shù)pthread_cond_signal和函數(shù) pthread_cond_broadcast喚醒線程被喚醒后,它將重新檢查判斷條件是否滿足,如果還不滿足,一般說來線程應該仍阻塞在這里,被等待被下一次喚醒。這個過程一般用while語句實現(xiàn)。
    通過下面的程序來理解:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /*初始化互斥鎖*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;  //初始化條件變量
void *thread1(void *);
void *thread2(void *);
int i=1;
int main(void)
{
        pthread_t t_a;
        pthread_t t_b;
        pthread_create(&t_a,NULL,thread1,(void *)NULL);/*創(chuàng)建進程t_a*/
        pthread_create(&t_b,NULL,thread2,(void *)NULL); /*創(chuàng)建進程t_b*/
        pthread_join(t_b, NULL);/*等待進程t_b結(jié)束*/
        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);
         exit(0);
}
void *thread1(void *junk)
{
        for(i=1;i<=9;i++)
        {
             printf("IN one\n"); 
             pthread_mutex_lock(&mutex);//
             if(i%3==0)
                 pthread_cond_signal(&cond);/*條件改變,發(fā)送信號,通知t_b進程*/
              else      
                  printf("thead1:%d\n",i);
              pthread_mutex_unlock(&mutex);//*解鎖互斥量*/
              printf("Up  Mutex\n");     
       sleep(10);
        }
}
void *thread2(void *junk)
{
        while(i<9)
        {
      
             printf("IN two \n"); 
              pthread_mutex_lock(&mutex);
            if(i%3!=0)
                   pthread_cond_wait(&cond,&mutex);/*等待*/
            printf("thread2:%d\n",i);
            pthread_mutex_unlock(&mutex);
            printf("Down  Mutex\n");
            sleep(10);
 }
}
----------------------------
IN one
thead1:1
Up  Mutex
IN two
IN one
thead1:2
Up  Mutex
IN one
Up  Mutex
thread2:3
Down  Mutex
IN one
thead1:4
Up  Mutex
IN two
IN one
thead1:5
Up  Mutex
IN one
Up  Mutex
thread2:6
Down  Mutex
IN one
thead1:7
Up  Mutex
IN two
IN one
thead1:8
Up  Mutex
IN one
Up  Mutex
thread2:9
Down  Mutex
-------
總結(jié)
pthread_cond_wait()是在當點  unlock 等待常量,其他線程就可以得到鎖了,當?shù)玫絪ignal時候會又會lock,,,,,繼續(xù)往當點走,直到unlock,
加強----------
使用條件變量
本節(jié)介紹如何使用條件變量。表 4–6 列出了可用的函數(shù)。
表 4–6 條件變量函數(shù)  操作
 相關(guān)函數(shù)說明
 
初始化條件變量
 pthread_cond_init 語法
 
基于條件變量阻塞
 pthread_cond_wait 語法
 
解除阻塞特定線程
 pthread_cond_signal 語法
 
在指定的時間之前阻塞
 pthread_cond_timedwait 語法
 
在指定的時間間隔內(nèi)阻塞
 pthread_cond_reltimedwait_np 語法
 
解除阻塞所有線程
 pthread_cond_broadcast 語法
 
銷毀條件變量狀態(tài)
 pthread_cond_destroy 語法
 
 
初始化條件變量
使用 pthread_cond_init(3C) 可以將 cv 所指示的條件變量初始化為其缺省值,或者指定已經(jīng)使用 pthread_condattr_init() 設(shè)置的條件變量屬性。

pthread_cond_init 語法
int pthread_cond_init(pthread_cond_t *cv,
    const pthread_condattr_t *cattr);
#include <pthread.h>
 
pthread_cond_t cv;
pthread_condattr_t cattr;
int ret;
 
/* initialize a condition variable to its default value */
ret = pthread_cond_init(&cv, NULL);
 
/* initialize a condition variable */
ret = pthread_cond_init(&cv, &cattr); cattr 設(shè)置為 NULL。將 cattr 設(shè)置為 NULL 與傳遞缺省條件變量屬性對象的地址等效,但是沒有內(nèi)存開銷。對于 Solaris 線程,請參見cond_init 語法。
使用 PTHREAD_COND_INITIALIZER 宏可以將以靜態(tài)方式定義的條件變量初始化為其缺省屬性。PTHREAD_COND_INITIALIZER 宏與動態(tài)分配具有 null 屬性的 pthread_cond_init() 等效,但是不進行錯誤檢查。
多個線程決不能同時初始化或重新初始化同一個條件變量。如果要重新初始化或銷毀某個條件變量,則應用程序必須確保該條件變量未被使用。

pthread_cond_init 返回值
pthread_cond_init() 在成功完成之后會返回零。其他任何返回值都表示出現(xiàn)了錯誤。如果出現(xiàn)以下任一情況,該函數(shù)將失敗并返回對應的值。
EINVAL
描述:
cattr 指定的值無效。
EBUSY
描述:
條件變量處于使用狀態(tài)。
EAGAIN
描述:
必要的資源不可用。
ENOMEM
描述:
內(nèi)存不足,無法初始化條件變量。

基于條件變量阻塞
使用 pthread_cond_wait(3C) 可以以原子方式釋放 mp 所指向的互斥鎖,并導致調(diào)用線程基于 cv 所指向的條件變量阻塞。對于 Solaris 線程,請參見cond_wait 語法。

pthread_cond_wait 語法
int pthread_cond_wait(pthread_cond_t *cv,pthread_mutex_t *mutex);
#include <pthread.h>
 
pthread_cond_t cv;
pthread_mutex_t mp;
int ret;
 
/* wait on condition variable */
ret = pthread_cond_wait(&cv, &mp); 阻塞的線程可以通過 pthread_cond_signal() 或 pthread_cond_broadcast() 喚醒,也可以在信號傳送將其中斷時喚醒。
不能通過 pthread_cond_wait() 的返回值來推斷與條件變量相關(guān)聯(lián)的條件的值的任何變化。必須重新評估此類條件。
pthread_cond_wait() 例程每次返回結(jié)果時調(diào)用線程都會鎖定并且擁有互斥鎖,即使返回錯誤時也是如此。
該條件獲得信號之前,該函數(shù)一直被阻塞。該函數(shù)會在被阻塞之前以原子方式釋放相關(guān)的互斥鎖,并在返回之前以原子方式再次獲取該互斥鎖。
通常,對條件表達式的評估是在互斥鎖的保護下進行的。如果條件表達式為假,線程會基于條件變量阻塞。然后,當該線程更改條件值時,另一個線程會針對條件變量發(fā)出信號。這種變化會導致所有等待該條件的線程解除阻塞并嘗試再次獲取互斥鎖。
必須重新測試導致等待的條件,然后才能從 pthread_cond_wait() 處繼續(xù)執(zhí)行。喚醒的線程重新獲取互斥鎖并從 pthread_cond_wait() 返回之前,條件可能會發(fā)生變化。等待線程可能并未真正喚醒。建議使用的測試方法是,將條件檢查編寫為調(diào)用 pthread_cond_wait() 的 while() 循環(huán)。

    pthread_mutex_lock();
        while(condition_is_false)
            pthread_cond_wait();
    pthread_mutex_unlock();如果有多個線程基于該條件變量阻塞,則無法保證按特定的順序獲取互斥鎖。

--------------------------------------------------------------------------------
注 –
pthread_cond_wait() 是取消點。如果取消處于暫掛狀態(tài),并且調(diào)用線程啟用了取消功能,則該線程會終止,并在繼續(xù)持有該鎖的情況下開始執(zhí)行清除處理程序。

--------------------------------------------------------------------------------

pthread_cond_wait 返回值
pthread_cond_wait() 在成功完成之后會返回零。其他任何返回值都表示出現(xiàn)了錯誤。如果出現(xiàn)以下情況,該函數(shù)將失敗并返回對應的值。
EINVAL
描述:
cv 或 mp 指定的值無效。

解除阻塞一個線程
對于基于 cv 所指向的條件變量阻塞的線程,使用 pthread_cond_signal(3C) 可以解除阻塞該線程。對于 Solaris 線程,請參見cond_signal 語法。

pthread_cond_signal 語法
int pthread_cond_signal(pthread_cond_t *cv);
#include <pthread.h>
 
pthread_cond_t cv;
int ret;
 
/* one condition variable is signaled */
ret = pthread_cond_signal(&cv); 應在互斥鎖的保護下修改相關(guān)條件,該互斥鎖用于獲得信號的條件變量中。否則,可能在條件變量的測試和 pthread_cond_wait() 阻塞之間修改該變量,這會導致無限期等待。
調(diào)度策略可確定喚醒阻塞線程的順序。對于 SCHED_OTHER,將按優(yōu)先級順序喚醒線程。
如果沒有任何線程基于條件變量阻塞,則調(diào)用 pthread_cond_signal() 不起作用。
 
--------------------------------------------------------------------------------
示例 4–8 使用 pthread_cond_wait() 和 pthread_cond_signal()
 
pthread_mutex_t count_lock;
pthread_cond_t count_nonzero;
unsigned count;
 
decrement_count()
{
    pthread_mutex_lock(&count_lock);
    while (count == 0)
        pthread_cond_wait(&count_nonzero, &count_lock);
    count = count - 1;
    pthread_mutex_unlock(&count_lock);
}
 
increment_count()
{
    pthread_mutex_lock(&count_lock);
    if (count == 0)
        pthread_cond_signal(&count_nonzero);
    count = count + 1;
    pthread_mutex_unlock(&count_lock);
}
--------------------------------------------------------------------------------

pthread_cond_signal 返回值
pthread_cond_signal() 在成功完成之后會返回零。其他任何返回值都表示出現(xiàn)了錯誤。如果出現(xiàn)以下情況,該函數(shù)將失敗并返回對應的值。
EINVAL
描述:
cv 指向的地址非法。
示例 4–8 說明了如何使用 pthread_cond_wait() 和 pthread_cond_signal()。

在指定的時間之前阻塞
pthread_cond_timedwait(3C) 的用法與 pthread_cond_wait() 的用法基本相同,區(qū)別在于在由 abstime 指定的時間之后 pthread_cond_timedwait() 不再被阻塞。

pthread_cond_timedwait 語法
int pthread_cond_timedwait(pthread_cond_t *cv,
    pthread_mutex_t *mp, const struct timespec *abstime);
#include <pthread.h>
#include <time.h>
 
pthread_cond_t cv;
pthread_mutex_t mp;
timestruct_t abstime;
int ret;
 
/* wait on condition variable */
ret = pthread_cond_timedwait(&cv, &mp, &abstime); pthread_cond_timewait() 每次返回時調(diào)用線程都會鎖定并且擁有互斥鎖,即使 pthread_cond_timedwait() 返回錯誤時也是如此。 對于 Solaris 線程,請參見cond_timedwait 語法。
pthread_cond_timedwait() 函數(shù)會一直阻塞,直到該條件獲得信號,或者最后一個參數(shù)所指定的時間已過為止。

--------------------------------------------------------------------------------
注 –
pthread_cond_timedwait() 也是取消點。

--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------

示例 4–9 計時條件等待
 
pthread_timestruc_t to;
pthread_mutex_t m;
pthread_cond_t c;
...
pthread_mutex_lock(&m);
to.tv_sec = time(NULL) + TIMEOUT;
to.tv_nsec = 0;
while (cond == FALSE) {
    err = pthread_cond_timedwait(&c, &m, &to);
    if (err == ETIMEDOUT) {
        /* timeout, do something */
        break;
    }
}
pthread_mutex_unlock(&m);
--------------------------------------------------------------------------------

pthread_cond_timedwait 返回值
pthread_cond_timedwait() 在成功完成之后會返回零。其他任何返回值都表示出現(xiàn)了錯誤。如果出現(xiàn)以下任一情況,該函數(shù)將失敗并返回對應的值。
EINVAL
描述:
cv 或 abstime 指向的地址非法。
ETIMEDOUT
描述:
abstime 指定的時間已過。
超時會指定為當天時間,以便在不重新計算值的情況下高效地重新測試條件,如示例 4–9 中所示。

在指定的時間間隔內(nèi)阻塞
pthread_cond_reltimedwait_np(3C) 的用法與 pthread_cond_timedwait() 的用法基本相同,唯一的區(qū)別在于 pthread_cond_reltimedwait_np() 會采用相對時間間隔而不是將來的絕對時間作為其最后一個參數(shù)的值。

pthread_cond_reltimedwait_np 語法
int  pthread_cond_reltimedwait_np(pthread_cond_t *cv,
    pthread_mutex_t *mp,
   const struct timespec *reltime);
#include <pthread.h>
#include <time.h>
 
pthread_cond_t cv;
pthread_mutex_t mp;
timestruct_t reltime;
int ret;
 
/* wait on condition variable */
ret = pthread_cond_reltimedwait_np(&cv, &mp, &reltime); pthread_cond_reltimedwait_np() 每次返回時調(diào)用線程都會鎖定并且擁有互斥鎖,即使 pthread_cond_reltimedwait_np() 返回錯誤時也是如此。對于 Solaris 線程,請參見 cond_reltimedwait(3C)。pthread_cond_reltimedwait_np() 函數(shù)會一直阻塞,直到該條件獲得信號,或者最后一個參數(shù)指定的時間間隔已過為止。

--------------------------------------------------------------------------------
注 –
pthread_cond_reltimedwait_np() 也是取消點。

--------------------------------------------------------------------------------

pthread_cond_reltimedwait_np 返回值
pthread_cond_reltimedwait_np() 在成功完成之后會返回零。其他任何返回值都表示出現(xiàn)了錯誤。如果出現(xiàn)以下任一情況,該函數(shù)將失敗并返回對應的值。
EINVAL
描述:
cv 或 reltime 指示的地址非法。
ETIMEDOUT
描述:
reltime 指定的時間間隔已過。

解除阻塞所有線程
對于基于 cv 所指向的條件變量阻塞的線程,使用 pthread_cond_broadcast(3C) 可以解除阻塞所有這些線程,這由 pthread_cond_wait() 來指定。

pthread_cond_broadcast 語法
int pthread_cond_broadcast(pthread_cond_t *cv);
#include <pthread.h>
 
pthread_cond_t cv;
int ret;
 
/* all condition variables are signaled */
ret = pthread_cond_broadcast(&cv); 如果沒有任何線程基于該條件變量阻塞,則調(diào)用 pthread_cond_broadcast() 不起作用。對于 Solaris 線程,請參見cond_broadcast 語法。
由于 pthread_cond_broadcast() 會導致所有基于該條件阻塞的線程再次爭用互斥鎖,因此請謹慎使用 pthread_cond_broadcast()。例如,通過使用 pthread_cond_broadcast(),線程可在資源釋放后爭用不同的資源量,如示例 4–10 中所示。
 
--------------------------------------------------------------------------------

示例 4–10 條件變量廣播
 
pthread_mutex_t rsrc_lock;
pthread_cond_t rsrc_add;
unsigned int resources;
 
get_resources(int amount)
{
    pthread_mutex_lock(&rsrc_lock);
    while (resources < amount) {
        pthread_cond_wait(&rsrc_add, &rsrc_lock);
    }
    resources -= amount;
    pthread_mutex_unlock(&rsrc_lock);
}
 
add_resources(int amount)
{
    pthread_mutex_lock(&rsrc_lock);
    resources += amount;
    pthread_cond_broadcast(&rsrc_add);
    pthread_mutex_unlock(&rsrc_lock);
}
--------------------------------------------------------------------------------
請注意,在 add_resources() 中,首先更新 resources 還是首先在互斥鎖中調(diào)用 pthread_cond_broadcast() 無關(guān)緊要。
應在互斥鎖的保護下修改相關(guān)條件,該互斥鎖用于獲得信號的條件變量中。否則,可能在條件變量的測試和 pthread_cond_wait() 阻塞之間修改該變量,這會導致無限期等待。

pthread_cond_broadcast 返回值
pthread_cond_broadcast() 在成功完成之后會返回零。其他任何返回值都表示出現(xiàn)了錯誤。如果出現(xiàn)以下情況,該函數(shù)將失敗并返回對應的值。
EINVAL
描述:
cv 指示的地址非法。

銷毀條件變量狀態(tài)
使用 pthread_cond_destroy(3C) 可以銷毀與 cv 所指向的條件變量相關(guān)聯(lián)的任何狀態(tài)。對于 Solaris 線程,請參見cond_destroy 語法。

pthread_cond_destroy 語法
int pthread_cond_destroy(pthread_cond_t *cv);
#include <pthread.h>
 
pthread_cond_t cv;
int ret;
 
/* Condition variable is destroyed */
ret = pthread_cond_destroy(&cv); 請注意,沒有釋放用來存儲條件變量的空間。

pthread_cond_destroy 返回值
pthread_cond_destroy() 在成功完成之后會返回零。其他任何返回值都表示出現(xiàn)了錯誤。如果出現(xiàn)以下情況,該函數(shù)將失敗并返回對應的值。
EINVAL
描述:
cv 指定的值無效。

喚醒丟失問題
如果線程未持有與條件相關(guān)聯(lián)的互斥鎖,則調(diào)用 pthread_cond_signal() 或 pthread_cond_broadcast() 會產(chǎn)生喚醒丟失錯誤。
滿足以下所有條件時,即會出現(xiàn)喚醒丟失問題:

一個線程調(diào)用 pthread_cond_signal() 或 pthread_cond_broadcast()
另一個線程已經(jīng)測試了該條件,但是尚未調(diào)用 pthread_cond_wait()
沒有正在等待的線程
信號不起作用,因此將會丟失
僅當修改所測試的條件但未持有與之相關(guān)聯(lián)的互斥鎖時,才會出現(xiàn)此問題。只要僅在持有關(guān)聯(lián)的互斥鎖同時修改所測試的條件,即可調(diào)用 pthread_cond_signal() 和 pthread_cond_broadcast(),而無論這些函數(shù)是否持有關(guān)聯(lián)的互斥鎖。

生成方和使用者問題
并發(fā)編程中收集了許多標準的眾所周知的問題,生成方和使用者問題只是其中的一個問題。此問題涉及到一個大小限定的緩沖區(qū)和兩類線程(生成方和使用者),生成方將項放入緩沖區(qū)中,然后使用者從緩沖區(qū)中取走項。
生成方必須在緩沖區(qū)中有可用空間之后才能向其中放置內(nèi)容。使用者必須在生成方向緩沖區(qū)中寫入之后才能從中提取內(nèi)容。
條件變量表示一個等待某個條件獲得信號的線程隊列。
示例 4–11 中包含兩個此類隊列。一個隊列 (less) 針對生成方,用于等待緩沖區(qū)中出現(xiàn)空位置。另一個隊列 (more) 針對使用者,用于等待從緩沖槽位的空位置中提取其中包含的信息。該示例中還包含一個互斥鎖,因為描述該緩沖區(qū)的數(shù)據(jù)結(jié)構(gòu)一次只能由一個線程訪問。
 
--------------------------------------------------------------------------------
示例 4–11 生成方和使用者的條件變量問題
 
typedef struct {
    char buf[BSIZE];
    int occupied;
    int nextin;
    int nextout;
    pthread_mutex_t mutex;
    pthread_cond_t more;
    pthread_cond_t less;
} buffer_t;
 
buffer_t buffer;
--------------------------------------------------------------------------------
如示例 4–12 中所示,生成方線程獲取該互斥鎖以保護 buffer 數(shù)據(jù)結(jié)構(gòu),然后,緩沖區(qū)確定是否有空間可用于存放所生成的項。如果沒有可用空間,生成方線程會調(diào)用 pthread_cond_wait()。pthread_cond_wait() 會導致生成方線程連接正在等待 less 條件獲得信號的線程隊列。less 表示緩沖區(qū)中的可用空間。
與此同時,在調(diào)用 pthread_cond_wait() 的過程中,該線程會釋放互斥鎖的鎖定。正在等待的生成方線程依賴于使用者線程在條件為真時發(fā)出信號,如示例 4–12 中所示。該條件獲得信號時,將會喚醒等待 less 的第一個線程。但是,該線程必須再次鎖定互斥鎖,然后才能從 pthread_cond_wait() 返回。
獲取互斥鎖可確保該線程再次以獨占方式訪問緩沖區(qū)的數(shù)據(jù)結(jié)構(gòu)。該線程隨后必須檢查緩沖區(qū)中是否確實存在可用空間。如果空間可用,該線程會向下一個可用的空位置中進行寫入。
與此同時,使用者線程可能正在等待項出現(xiàn)在緩沖區(qū)中。這些線程正在等待條件變量 more。剛在緩沖區(qū)中存儲內(nèi)容的生成方線程會調(diào)用 pthread_cond_signal() 以喚醒下一個正在等待的使用者。如果沒有正在等待的使用者,此調(diào)用將不起作用。
最后,生成方線程會解除鎖定互斥鎖,從而允許其他線程處理緩沖區(qū)的數(shù)據(jù)結(jié)構(gòu)。
 
--------------------------------------------------------------------------------
示例 4–12 生成方和使用者問題:生成方
 
void producer(buffer_t *b, char item)
{
    pthread_mutex_lock(&b->mutex);
  
    while (b->occupied >= BSIZE)
        pthread_cond_wait(&b->less, &b->mutex);
 
    assert(b->occupied < BSIZE);
 
    b->buf[b->nextin++] = item;
 
    b->nextin %= BSIZE;
    b->occupied++;
 
    /* now: either b->occupied < BSIZE and b->nextin is the index
       of the next empty slot in the buffer, or
       b->occupied == BSIZE and b->nextin is the index of the
       next (occupied) slot that will be emptied by a consumer
       (such as b->nextin == b->nextout) */
 
    pthread_cond_signal(&b->more);
 
    pthread_mutex_unlock(&b->mutex);
}
--------------------------------------------------------------------------------
請注意 assert() 語句的用法。除非在編譯代碼時定義了 NDEBUG,否則 assert() 在其參數(shù)的計算結(jié)果為真(非零)時將不執(zhí)行任何操作。如果參數(shù)的計算結(jié)果為假(零),則該程序會中止。在多線程程序中,此類斷言特別有用。如果斷言失敗,assert() 會立即指出運行時問題。assert() 還有另一個作用,即提供有用的注釋。
以 /* now: either b->occupied ... 開頭的注釋最好以斷言形式表示,但是由于語句過于復雜,無法用布爾值表達式來表示,因此將用英語表示。
斷言和注釋都是不變量的示例。這些不變量是邏輯語句,在程序正常執(zhí)行時不應將其聲明為假,除非是線程正在修改不變量中提到的一些程序變量時的短暫修改過程中。當然,只要有線程執(zhí)行語句,斷言就應當為真。
使用不變量是一種極為有用的方法。即使沒有在程序文本中聲明不變量,在分析程序時也應將其視為不變量。
每次線程執(zhí)行包含注釋的代碼時,生成方代碼中表示為注釋的不變量始終為真。如果將此注釋移到緊挨 mutex_unlock() 的后面,則注釋不一定仍然為真。如果將此注釋移到緊跟 assert() 之后的位置,則注釋仍然為真。
因此,不變量可用于表示一個始終為真的屬性,除非一個生成方或一個使用者正在更改緩沖區(qū)的狀態(tài)。線程在互斥鎖的保護下處理緩沖區(qū)時,該線程可能會暫時聲明不變量為假。但是,一旦線程結(jié)束對緩沖區(qū)的操作,不變量即會恢復為真。
示例 4–13 給出了使用者的代碼。該邏輯流程與生成方的邏輯流程相對稱。
 
--------------------------------------------------------------------------------
示例 4–13 生成方和使用者問題:使用者
 
char consumer(buffer_t *b)
{
    char item;
    pthread_mutex_lock(&b->mutex);
    while(b->occupied <= 0)
        pthread_cond_wait(&b->more, &b->mutex);
 
    assert(b->occupied > 0);
 
    item = b->buf[b->nextout++];
    b->nextout %= BSIZE;
    b->occupied--;
 
    /* now: either b->occupied > 0 and b->nextout is the index
       of the next occupied slot in the buffer, or
       b->occupied == 0 and b->nextout is the index of the next
       (empty) slot that will be filled by a producer (such as
       b->nextout == b->nextin) */
 
    pthread_cond_signal(&b->less);
    pthread_mutex_unlock(&b->mutex);
 
    return(item);
}
本文來自CSDN博客,轉(zhuǎn)載請標明出處:http://blog.csdn.net/xiaochangfu/archive/2009/10/26/4729342.aspx

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多