2017-07-27 82 views
3

我有一個動態庫內的邏輯運行一些服務,是由主要的可執行文件請求。如何避免等待pthread_cond_t信號已發送

從庫代碼中調用start_service後,需要做好一些準備工作,在此期間,主代碼不應嘗試訪問該服務。

要在服務準備就緒時通知主代碼,我使用條件變量併發信號通知主可執行文件。

在主代碼等待條件變量之前,我希望聽到一些關於處理庫變得可用時的情況的最佳方法的建議。在這種情況下,等待能夠天長地久......

這裏的服務代碼:

extern pthread_cond_t cnd; 
extern pthread_mutex_t mtx; 

void start_service() 
{ 
    // getting serviceable.  
    pthread_cond_signal(&cnd); 
    main_loop(); 
} 

而這裏的主代碼。

pthread_cond_t cnd; 
pthread_mutex_t mtx; 

int main() 
{  
    pthread_cond_init(&cnd,NULL); 
    pthread_mutex_init(&mtx, NULL); 

    std::thread mytrd(&start_service); 
    ... 
    pthread_mutex_lock(&mtx); 

    pthread_cond_wait(&cnd, &mtx); // what happens if we get here after the signal already sent. 
    pthread_mutex_unlock(&mtx); 
    ... 
} 

P.S期望的行爲應該是主代碼避免等待條件變量,如果它已經發信號。

+0

您可以使用的'0'初始計數信號量,所以主要被阻塞,直到'start_service()'增加信號計數爲'1'.If主,'start_service塊調用之前() '將信號計數增加到'1',主要不會進入等待狀態。 –

+0

嗨,感謝您的評論,它似乎是一個合適的方式..也許你可以修改我的代碼來表達你的想法? – Zohar81

+0

pthread_wait **必須總是**在循環中使用,它具有它等待的條件。不使用循環是不好的做法,可能會在任何時候失敗。 – geza

回答

2

你需要一個謂詞和謂詞檢查封閉wait

pthread_mutex_lock(&mtx); 
    while(! predicate) pthread_cond_wait(&cnd, &mtx); 
    pthread_mutex_unlock(&mtx); 

這樣,線程犯規事件開始等待時,它並不需要。 您需要的第二個原因是爲了避免可能發生的虛假喚醒,即,即使其他線程未發出信號,pthread_cond_wait也可能會返回。然後

另一個線程必須做的(你需要鎖定互斥鎖來保護謂語):

pthread_lock_mutex(&mtx); 
predicate = true; 
pthread_cond_signal(&cnd); 
pthread_unlock_mutex(&mtx); 
+0

謂詞應該是全局變量,就像mtx和cnd一樣,對嗎? – Zohar81

+1

@ Zohar81:是的。但更好的是,將這些東西打包到一個結構中,並將其作爲參數傳遞給線程。這樣你可以避免全局變量,並且你可以有更多的服務。 – geza

+0

@ Zohar81如果你有權訪問C++ 11,你應該使用'',如果你不'''。至少應該使用一個作用域鎖,它在其構造函數中執行'pthread_mutex_lock',並在析構函數中執行'pthread_mutex_unlock'。通過這種方式,您不能忘記解鎖它(或者在發生異常時錯過鎖定它) – user463035818

2

您可以使用旗語與0初始計數,所以main被阻塞,直到start_service()增加信號計數到1。如果在main中的塊調用之前,start_service()將信號量計數增加到1,main將永遠不會進入等待狀態。如下所示。

void start_service() 
{ 
    // getting serviceable.  
    sem_post(&sem_mutex);//increases to 1 
    main_loop(); 
} 
int main() 
{ 
    sem_init(&sem_mutex, 0, 0);//initially blocked. 
    std::thread mytrd(&start_service); 
    sem_wait(&sem_mutex); 
    ... 
}