2011-05-26 89 views
3

我的守護進程在它開始執行任務之前,在四個不同的線程中初始化自己。現在我使用一個計數器,它在線程啓動時遞增並在完成時遞減。當計數器達到0時,我調用初始化完成的回調函數。多線程自旋鎖?

這是做這件事的首選方式,還是有更好的方法?我使用POSIX線程(pthread)我,我只是一個運行週期while等待櫃檯打0.1

編輯:pthread_barrier_*功能不可用我的平臺上,儘管他們似乎是最好的選擇。

編輯2:並非所有線程都退出。一些初始化,然後聽事件。基本上線程需要說,「我正在初始化」。

+0

請參閱Julio的回答。這是最好的方法。 – 2011-05-26 14:27:35

回答

3

與其使用spin,請使用pthread mutex/condvar基元。我建議使用單個互斥體來保護未完成線程的數量以及condvar。

主循環看起來是這樣的:

acquire mutex 
count=N_THREADS; 
start your N threads 
while (1) { 
    if (count==0) break; 
    cond_wait(condvar); 
} 
release mutex 

當每個線程就緒時,它會做這樣的事情:

acquire mutex 
count-- 
cond_signal(condvar) 
release mutex 

(編輯:我認爲線程是保持如果他們要完成,請使用pthread_join,正如別人所說的那樣)。

3

pthread_join是等待pthreads的首選方式。

+1

+1加入線程是最好的選擇。 – 2011-05-26 13:43:22

+2

這是等待特定線程的正確方法,但不是等待「N個線程」的正確方法。 – 2011-05-26 14:27:06

+0

他只需要等待四個線程中的每一個。如果其他線程繼續後續,屏障將是選擇。對我來說,所有的線程都等待對方,然後除了一個之外,都只是終止而已。 – 2011-05-27 08:43:12

0

正如KlasLindbäck在他的回答中指出的那樣,加入線程是首選方式。 如果你的線程沒有退出(即是可重用池的一部分等),邏輯聽起來不錯。唯一沒有任何同步的使用計數器是危險的。你必須使用條件或原子整數互斥。如果你不想在等待初始化完成的線程中使用原子計數器,我建議使用互斥+條件。

3

聽起來很奇怪。你不應該只是使用pthread_join()來等待線程完成嗎?也許我不明白這個問題。

+0

+1,用於提供鏈接到文檔 – JeremyP 2011-05-26 13:51:45

7

障礙是你需要的。它們是爲此而創建的,當你需要在某些點「見面」時才繼續。請參閱pthread_barrier_ *

+0

+1,用於爲工作推薦正確的工具,屏障。所有其他解決方案都不是最優的。 – 2011-05-26 14:08:26

+0

我開悟了! – crazyscot 2011-05-26 16:20:32

+0

繼續是這裏的詞。唯一的事情是,其他4個線程將不會繼續。障礙是偉大的,但在這裏使用它們可能會讓後來的代碼讀者感到困惑。簡而言之:當等待其他線程終止時,屏障是矯枉過正的。 – 2011-05-27 08:51:28

0

那麼,如果一個線程完成初始化在其他任何人開始之前?

所以一個辦法做到在每個線程與初始化,增量計數器做到了

  1. 初始化一個原子計數器爲0
  2. 並自動檢索該值。如果使用GCC,則可以使用__sync_add_and_fetch()
  3. 如果檢索到的計數器值爲< N_threads,則阻塞pthread條件變量。
  4. 如果檢索到的計數器值== N_threads,初始化階段完成,則發出信號並繼續。