2015-03-13 238 views
1

我回到使用pthreads和pthread_join的定義困擾我。多次調用pthread_join如何工作?

它說

「的在pthread_join(),直到目標線程終止函數應暫停調用 線程的執行,除非目標線程 已經終止。從成功的在pthread_join()返回 調用時使用非NULL的value_ptr參數,由終止線程傳遞給 pthread_exit()的值應在 中由value_ptr引用的位置可用。當pthread_join()成功返回 時,目標線程已終止。結果爲 多個同時調用pthread_join()指定相同的目標線程 未定義。如果線程調用pthread_join()是 取消,則目標線程不得超脫。」

我想了解,如果我叫在pthread_join一個線程,然後調用pthread_join完成啓動第二個線程,兩個線程都會啓動,即使我想象中,第二個pthread_join也不能被調用,因爲第一個連接暫停了主線程的執行,並且運行下一行,直到pthread_exit從被連接的線程中調用。

In特別是,我想,第一個pthread_join必須等到指定的線程調用pthread_exit後,纔會繼續執行。但事實並非如此,因爲我可以這樣做:

#include <pthread.h> 
#include <stdio.h> 

int avail = 0; 

void *consumer(void *unused) 
{ 
    while (1) { 
     if (avail > 0) { 
      --avail; 
      puts("consumed"); 
     } 
    } 
} 

void *producer(void *unused) 
{ 
    while (1) { 
     ++avail; 
     puts("produced"); 
    } 
} 

int main(int argc, char **argv) 
{ 
    pthread_t c_thread; 
    pthread_t p_thread; 
    pthread_create(&c_thread, 0, consumer, 0); 
    pthread_create(&p_thread, 0, producer, 0); 
    pthread_join(c_thread, 0); 
    pthread_join(p_thread, 0); 

    return 0; 
} 

忽略可能的競爭條件的問題,以儘量減少代碼大小,爲什麼都是工作,儘管線程先加入暫停主線程(因此,防止下一個被稱爲加入,在我心中)。

我真的很想知道這是如何工作的。

提前致謝。

+2

「我爲一個線程調用pthread_join,然後調用pthread_join創建第二個線程」 - ''pthread_join()'不創建線程。也就是說,你的「問題」缺乏對你所看到的和你期望看到的東西的精確描述。還要注意,你對你所看到的內容的解釋不如你實際看到的重要。 – 2015-03-13 18:48:06

+1

您可以添加一個睡眠呼叫或調用'scanf()'等待輸入或設置斷點。調度程序在創建後不會立即切換到其他線程。也就是說,你可以很容易地檢查第二個'pthread_join()'是否被調用,或者至少如果第一個返回。 – 2015-03-13 18:59:29

+0

好吧,這是有道理的,所以聯接基本上是一個非繁忙的等待線程在程序恢復之前完成。線程確實由pthread_create創建並啓動,但需要時間才能真正運行,因爲如果沒有告訴等待任何事情,main將會提前退出。 – Dmitry 2015-03-13 19:01:51

回答

5

線程同時運行,在致電pthread_create期間或之後的某個時間開始。調用pthread_join與啓動或運行線程無關,只是等到它退出。你的線程已經在運行,並且在第一次加入的時候仍然可以運行,並且它們將繼續運行。唯一被第一個連接阻塞的是你的主線程。

+0

你說得對,我看到的是,如果我刪除了連接,程序就提前退出,因爲它沒有在任何線程上等待完成。如果我使用while循環(1){}「而不是連接」,則線程仍會運行。謝謝! – Dmitry 2015-03-13 18:58:17

+0

當'main'返回時程序終止。 (我相信標準說從main返回相當於調用'exit')這包括終止所有線程。線程目前可能運行也可能不運行,這取決於線程的計劃運行方式,這取決於您的平臺。 – 2015-03-13 19:00:27

0

線程不是在pthread_join中開始,而是在pthread_create中開始。我誤以爲pthread_join被用來實際啓動線程,而在主線程繼續執行之前它是一個非繁忙的等待特定線程返回,在我的情況下,主線程返回之前線程有機會致電puts函數。

我的代碼中的第二個pthread_join從來沒有實際調用,因爲main實際上是從第一個等待c_thread返回的pthread_join掛起的。在這個特定場景中的第二次連接是「無操作」,並且程序從未實際得到它,因爲消費者從未實際返回。