2012-11-14 77 views
1

我用等待條件和互斥從Linux上的並行線程做處理之間的同步一個奇怪的問題。請注意,這不僅僅是一個進程中的線程之間。線程在多進程設置等待等待條件沒有被驚醒

我的使用情況是有創建資源(在我的圖片),並將它們保存到共享內存區,更新關於資源的一些信息,然後信號等待消費者的生產者。共享內存和元數據部分工作正常,所以我會離開它,問題是信號無法可靠地工作。用例很簡單,因爲消費者如果丟失一個或兩個圖像並不重要,如果消費者還沒有時間讀取它,生產者基本上只覆蓋一箇舊圖像。所以等待條件只需要處理喚醒消費者,我不需要有任何資源計數或其他數據。

兼顧生產者和消費者有這樣的結構:

struct EventData { 
    pthread_mutex_t mutexHandle; 
    pthread_cond_t conditionHandle; 
}; 

在消費過程中的線程坐着等待事情發生:

pthread_mutex_lock(&eventData->mutexHandle); 
pthread_cond_wait(&eventData->conditionHandle, &eventData->mutexHandle); 
thread_mutex_unlock(&eventData->mutexHandle); 

生產過程做到這一點時,它創建了一個圖像,將其保存到共享內存中,並準備讓消費者抓取圖像:

pthread_mutex_lock(&eventData->mutexHandle); 
pthread_cond_signal(&eventData->conditionHandle); 

// also tried: 
//pthread_cond_broadcast(&eventData->conditionHandle); 
pthread_mutex_unlock(&eventData->mutexHandle); 

這對我來說看起來相當不錯,它在某種程度上起作用。製片人可以在沒有任何問題的情況下向消費者發出大約100-1000次的信號,消費者醒來,抓住圖像並顯示它,結果是我可以看到移動的視頻。在某些時候,通常大約幾百幀,消費者將在pthread_cond_wait()中凍結,並且永遠不會返回。製作人仍然樂意創建圖像,調用pthread_cond_signal()並繼續沒有問題。消費者並沒有完全凍結,只有執行pthread_cond_wait()的線程,其他應用程序運行沒有問題。

那麼,什麼原因,當它從一個線程移動到另一個線程在另一個進程中迷路的信號。消費者凍結前通常需要5-20秒,醒來的次數也會在100到1000之間變化(根據迄今爲止的數值)。

互斥體,等待條件不平凡的默認進程間共享,我用這個設置創建原語:

EventData * eventData; 

    int fd = open(tmpnam(NULL), O_RDWR | O_CREAT | O_EXCL, 0666); 
    if (fd < 0) { 
     // failed to open file for event 
    } 

    if (ftruncate(fd, sizeof (eventData)) < 0) { 
     // failed to truncate file 
    } 

    // setup attributes to allow sharing between processes 
    pthread_condattr_init(&conditionAttribute); 
    pthread_condattr_setpshared(&conditionAttribute, PTHREAD_PROCESS_SHARED); 
    pthread_mutexattr_init(&mutexAttribute); 
    pthread_mutexattr_setpshared(&mutexAttribute, PTHREAD_PROCESS_SHARED); 

    // map memory for the event struct 
    eventData = (EventData *) mmap(NULL, sizeof(EventData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
    close (fd); 

    // finally initialize the memory 
    pthread_mutex_init(&eventData->mutexHandle, &mutexAttribute); 
    pthread_cond_init(&eventData->conditionHandle, &conditionAttribute); 

以上是由創建互斥黨完成和等待條件。該文件,即使用tmpnam(NULL)的名稱是在保存和傳遞給其他進程打開的現實:

int fd = open(nameOfEventFile, O_RDWR, 0666); 
    if (fd < 0) { 
     // failed to open file for event 
    } 

    eventData = (EventData *) mmap(NULL, sizeof(EventData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
    close(fd); 

我在這裏沒有看到錯誤,並希望一些線索,以什麼可能出問題,尤其是它隨機運行一些時間。

+0

請注意,一般來說,您希望在'while(!some_condition)pthread_cond_wait(...);'等循環中使用'pthread_cond_wait'。這應該防止您等待可能已經發生的事件。 – Hasturkun

回答

1

而且只要我寫的錯誤戳我的眼睛問題的95%......我還是decied把它在這裏與在類似的情況下,別人絆倒修復一起。其中創建互斥,等待條件的部分看起來像這樣:

EventData * eventData; 

int fd = open(tmpnam(NULL), O_RDWR | O_CREAT | O_EXCL, 0666); 
if (fd < 0) { 
    // failed to open file for event 
} 

if (ftruncate(fd, sizeof (eventData)) < 0) { 
    // failed to truncate file 
} 

如果你仔細看,你看到ftruncate()截斷到EVENTDATA指針的大小,而不是結構EVENTDATA的大小。所以,這裏需要的一個字符修復是:

if (ftruncate(fd, sizeof (EventData)) < 0) { 
    // failed to truncate file 
} 

確實是一個愚蠢的錯誤。

+2

更靈活的解決方案是使用'sizeof(* eventData)'。所以,即使「eventData」的定義會改變,也不需要調用「ftruncate()」調用。 – alk