2015-10-19 83 views
2
#include <iostream> 
#include <iostream> 

static const int num_threads = 5000; 

void thread_fun() { 
    ... 
} 

int main() { 
    std::thread t[num_threads]; 

    //Launch threads 
    for (int i = 0; i < num_threads; ++i) { 
     t[i] = std::thread(thread_fun); 
    } 

    //Join threads with the main thread 
    for (int i = 0; i < num_threads; ++i) { 
     t[i].join(); 
    } 

    return 0; 
} 

當5000個線程開始運行並執行void thread_fun()時,將如何處理thread_fun()C++線程函數說明

  1. 會有隻能是thread_fun()一個副本在5000個線程訪問它的主程序的堆棧?

  2. 是否會在主程序的堆棧上創建thread_fun()的5000份副本,並且每個線程都可以訪問自己的thread_fun()副本?

  3. thread_fun()加載到5000個線程的每個堆棧中,而不是主程序堆棧中?

我開始學習C++線程,並想知道如何處理這種情況。

+0

通常線程將使用線程局部堆棧。唯一共享的數據結構是堆分配。將線程本地數據從一個線程傳遞到另一個線程的指針是非常危險且最好避免的。 (使用無數據) – tadman

+0

4)5000線程不共享任何東西,但獨立的功能從所有我至今讀。有堆棧和堆空間。一個函數被放入堆棧並在完成時被移除。這是我所指的堆棧。對於第三個問題。我讀的是每個線程都有自己的大約2MB的堆棧。我在問是否這是功能加載和運行的空間。 –

+0

每個線程都有自己的堆棧 – Adam

回答

0

所有這些問題的簡短答案是否定的。代碼不存儲在堆棧中。 thread_fun只有一個副本,它存在於代碼段中。操作系統將分配內部數據結構,用來調度cpu上的線程(每個線程有一個棧,線程本地存儲,寄存器和指令指針的存儲等)。

你有什麼堆棧的main()是std :: thread類型的數組。

0

正如您懷疑的那樣,將會有一個副本thread_fun,它將由併發線程執行。參數化線程函數的正常方法是使用線程函數對象(例如從std::bind返回的類型)。

至於5000線程......你會很幸運! 200正在推動大多數系統的限制。如果你需要那麼多的併發性,你會想研究「異步編程模型」。

1

首先,C++線程在操作系統線程上非常薄(在我自己看來太薄)層 - Posix系統的pthread或Windows的Windows線程。問題不在於C++線程,而在於一般線程 - 實際上是硬件體系結構。

  1. 在主程序的堆棧中只有一個thread_fun()副本,其中5000個線程訪問它?

這取決於你的意思是'堆'。如果你正在談論應用程序堆棧內存,那麼這個問題就沒有意義了。函數不分配在堆棧上。函數是代碼,實際上不能以這種方式分配代碼。然而,如果'堆棧'意思是'堆棧跟蹤',那麼5000個線程將產生5000個堆棧跟蹤(當用像pstack這樣的例程進行查看時),並且這5000個堆棧跟蹤中的每一個都會有thread_fun

  • 意志thread_fun() 5000個拷貝主程序的堆疊上被創建並且每個線程將具有到其自己的副本thread_fun()存取?
  • 參見上文。代碼將永遠不會分配到堆棧上。只有一個thread_fun CODE實例。可能有多個由thread_fun操縱的不同數據點的實例。

    1. thread_fun()加載到每個5000線程的自己的堆棧中,而不是在主程序堆棧中?

    我不明白這個問題。

    +0

    我有點新的C++,但 – WhatIf

    +0

    @WhatIf,這就是爲什麼你感到困惑。函數本身從不「放置」在堆棧上。決不。功能被執行。局部變量可以通過函數在堆棧上分配,也可以由函數釋放。只有數據進入堆棧,而不是代碼 - 功能不是數據,而是代碼。 – SergeyA

    2

    每個線程都有它自己的堆棧,並且每次線程調用一個函數時,所有局部變量(從堆棧內部調用)和狀態將分別存儲在線程堆棧內部。

    enter image description here

    所有全局和動態分配的變量存儲在過程memory.Note的獨立的部分:永遠不要把它叫做程序存儲器,因爲在創建內存當一個程序變成一個過程,我的意思是,當一個程序開始運行纔會創建此內存結構(請參閱圖像)。

    現在三個問題可能會出現:

    1)如果我打電話從Thread一個全局變量?

    這個問題的答案是,所有的全局數據存儲在程序存儲器的「初始化段」內。(見圖片)

    2)如果我動態地分配一些數據是什麼?

    答案是幾乎所有動態分配的內存(使用malloc,new等)都存儲在程序存儲器的「堆」部分內(見圖)。這個堆部分可以動態增長它並不能確定程序在運行時分配多少內存。看到圖像。在這裏,我們的堆可以動態向上(注意:在一些圖中,堆可能會顯示爲向下動態增長,但這並不重要)。

    3)數據是如何存儲在Thread的堆棧中的,並且是動態分配的?

    讓我們考慮一個正常的函數調用。當一個程序調用一個函數時,它使用的所有局部變量都存儲在進程內存的「棧」部分內(見圖)。這個堆棧動態增長!是的,它的原因是一個函數可能會執行一些遞歸調用,它獨立於我們的程序/輸入將執行多少次遞歸調用。 線程遵循類似的過程。當一個線程被創建時,堆棧的某些部分將以線程堆棧的形式保留在進程內存中(見圖)。

    現在讓我們來回答你的問題: Ans 1)不,你問他問題的方式是錯誤的。在主程序的堆棧中不會有「thread_fun()的一個副本」。 thread_fun()的所有代碼都將存儲在進程內存的「text」部分中,但會被調用5000次。每次它由一個獨特的線程調用時,都會創建一個新的線程堆棧,其中將存儲局部變量和狀態的所有值。 答2)閱讀答案1只 答3)讀取答2:P

    請嘗試背誦和學習的東西在圖片和閱讀書籍,如Linux編程接口和,讓您的概念更強。希望有所幫助:)

    圖片取自Linux編程接口。