2013-02-22 29 views
0

我想用C++來解決Dining philosophers problempthread_cond_wait奇怪的行爲

代碼編譯爲g++ -lpthread

整個解決方案在philosophers github。存儲庫包含兩個cpp文件:main.cpp和philosopher.cpp。 「Main.cpp」創建互斥變量,信號量,5個條件變量,5個分支,並啓動哲學家。信號量僅用於同步哲學家的開端。其他參數傳遞給哲學家來解決問題。 「Philosopher.cpp」包含給定問題的解決方案,但發生幾個步驟後會發生死鎖。

當哲學家0吃東西時,會發生僵局,哲學家1(在他旁邊)想要分叉。然後,哲學家1已經採取互斥,並且不會放棄,直到哲學家0放下他的叉子。由於被互斥了,哲學家0不能放下他的叉子,所以我們陷入了僵局。問題出在Philosopher :: take_fork方法中,調用pthread_cond_wait(a,b)不釋放互斥量b。無法弄清楚爲什麼?

// Taking fork. If eather lef or right fork is taken, wait. 
void Philosopher::take_fork(){ 
    pthread_mutex_lock(&mon); 
    std::cout << "Philosopher " << id << " is waiting on forks" << std::endl; 
    while(!fork[id] || !fork[(id + 1)%N]) 
    pthread_cond_wait(cond + id, &mon); 
    fork[id] = fork[(id + 1)%N] = false; 
    std::cout << "Philosopher " << id << " is eating" << std::endl; 
    pthread_mutex_unlock(&mon); 
} 

其餘的請參考this code

回答

1

您致電pthread_cond_wait()是好的,所以問題必須在其他地方。您可以看到三個錯誤:

首先,在main()中,您只是初始化條件變量中的第一個數組。您需要初始化所有N條件變量:

for(int i = 0; i < N; i++) { 
    fork[i] = true; 
    pthread_cond_init(&cond[i], NULL); 
} 

pthread_mutex_init(&mon, NULL); 

其次,在put_fork()你有一個不正確的計算條件變量的一個信號:

pthread_cond_signal(cond + (id-1)%N); /* incorrect */ 

id等於零,(id - 1) % N是等於-1,所以這會嘗試發信號cond - 1,它並不指向一個條件變量(這個指針實際上可能破壞了你的互斥量,因爲它可能直接放在堆棧上的cond之前)。你真正想要的計算公式爲:

pthread_cond_signal(cond + (id + N - 1) % N); 

第三個錯誤是不是你的死鎖的原因,但你不應該叫srand(time(NULL))每次調用rand()時間 - 只是打電話,有一次,在main()開始。

+0

謝謝。問題在於未初始化所有條件變量。 – akegalj 2013-03-02 16:16:46