2013-06-28 42 views
0

我想寫一個多線程的代碼,但我有一個小問題。 在我的程序中,我有兩種類型的線程,探索者(我有4個或5個)和main(我有其中之一)。我想讓所有的探索者線程同時運行,當他們完成主線程開始工作時。有一個循環,我做了以上的事情一遍又一遍。由於創建線程的開銷,我決定在main運行時讓探索者線程休眠,並在完成時喚醒它(當然反之亦然)。爲了實現這個目標,我使用了障礙。下面是我的線程的僞代碼:線程在pthread停止工作後一些改動

主線程功能:

void* main(void* arg) 
{ 
    while(true) 
    { 
     wait_for_barrier_1 

     do_your_job 

     reset_barrier_1 
     wait_for_barrier_2 
    } 
} 

探險線程函數

void* explorers(void* arg) 
{ 
    while(true) 
    { 

     do_your_job 

     wait_for_barrier_1   

     if(thread_id == 0) 
     { 
      reset_barrier_2 
     }    

     wait_for_barrier_2 
    } 
} 

barrier_1用於防止主運行結束探險之前,和barrier_2使用在結束main之前阻止探險家。

我的問題是這段代碼不能正常工作。在開始時它工作正常,但經過兩三次迭代後,一些瀏覽器線程突然停止工作,所以整個程序將停止工作。

我無法弄清楚,特別是因爲沒有規則的迭代次數。在一些運行中,它會在第一次迭代之後停止,而在另一些運行中它可以正常工作,直到第5次或第6次。

順便說一下,我使用的是Mac OSX。

+0

信號量,也許... –

+2

我們確實需要看到實際的代碼。 –

回答

0

其實問題很重要,因爲當你重置一個障礙時,它會失去它的記憶並忘記之前的多線程到達它。因此,例如Explorer可能會等待Barrier1,然後時間到達主要通道Barrier1完成其工作,並在Explorer獲得通過它之前重置它。所以在這種情況下,main正在等待Barrier2並且瀏覽器正在等待Barrier1(它被main復位)

爲了解決這個問題,我爲每個障礙使用了兩個障礙變量,並在迭代中在它們之間切換。以下是我的僞代碼。它工作得很好。

主要功能:

void* main(void* arg) 
{ 
    bool turn = false; 

    while(true) 
    { 
     if(turn) 
     { 
      wait_for_barrier_1 
     } 
     else 
     { 
      wait_for_barrier_1_P 
     } 

     do_your_job 

     if(turn) 
     { 
      reset_barrier_1_P 
     } 
     else 
     { 
      reset_barrier_1 
     } 

     if(turn) 
     { 
      wait_for_barrier_2 
     } 
     else 
     { 
      wait_for_barrier_2_P 
     } 

     turn = !turn ; 
    } 
} 

資源管理器功能:

void* main(void* arg) 
{ 
    bool turn = false; 

    while(true) 
    { 
     do_your_job 

     if(turn) 
     { 
      reset_barrier_2 
     } 
     else 
     { 
      reset_barrier_2_P 
     } 

     if(turn) 
     { 
      wait_for_barrier_1 
     } 
     else 
     { 
      wait_for_barrier_1_P 
     } 


     if(turn) 
     { 
      wait_for_barrier_2 
     } 
     else 
     { 
      wait_for_barrier_2_P 
     } 

     turn = !turn ; 
    } 
} 

我知道這是一個有些凌亂,但它工作正常。

2

是最好的,我可以回答沒有看到實際的代碼,似乎可能主要是通過wait_for_barrier_2 通過之前的探險家線程reset_barrier_2。

所以主循環回到wait_for_barrier_1,然後然後資源管理器線程reset_barrier_2和wait_for_barrier_2。當這樣的主要等待1,探索者等待2,沒有人收益。

事情是這樣的:

Iteration 1: 
main wait_for_barrier_1 
         explorers do_your_job 
         explorers wait_for_barrier_1 
main do_your_job 
         explorers reset_barrier_2 
         explorers wait_for_barrier_2 
main reset_barrier_1 
main wait_for_barrier_2 
main wait_for_barrier_1… 

Iteration 2: 
…main wait_for_barrier_1 
         explorers do_your_job 
         explorers wait_for_barrier_1 
main do_your_job 
main reset_barrier_1 
main wait_for_barrier_2 (but it hasn't been reset yet! Runs right through!) 
main wait_for_barrier_1 
         explorers reset_barrier_2 
         explorers wait_for_barrier_2 

Deadlock! 

我認爲,如果你reset_barrier_2你wait_for_barrier_1,主要的方式,將無法通過wait_for_barrier_2急於之前,它是重置之前它可能工作。

+0

實際上,當我按照你所說的切換命令時,我遇到了同樣的問題。問題是當你重置一個障礙時,它忘記了它的最後一個。因此,有時例如資源管理器正在等待B1,然後時間去主要,主要做它的工作和重置B1,在探險家有機會通過它之前... 我解決了我的問題,通過使用兩個障礙變量爲每個障礙和在迭代中切換它們。 順便說一句,感謝這個想法,它真的鼓勵我尋找這種類型的死鎖。 – mmohaveri