2015-12-11 91 views
-3

我做的多線程在C++中。我在Windows上。 這是我有:C++中止被稱爲

int i; 
    try { 
     std::vector<std::thread> threads; 
     for (i = 0; i < threadscount; i++) { 
      threads.push_back(std::thread(myvoid)); 
      std::cout << "started\n"; 
     } 

     for (i = 0; i < threadscount; i++) { 
      threads[i].join(); 
      std::cout << "joined\n"; 
     } 
    } 
    catch (...) {} 

但是,當我設置threadscount到2000多個線程我得到:

中止()被調用。

爲什麼會出現這種情況?我可以得到解決方案來解決這個問題嗎?

+1

如果你真的想知道,在運行調試你的代碼;當中止被調用時它應該暫停。正如SergeyA指出的那樣,2000線程是過度殺傷。 –

+5

32位或64位?每個線程都需要2M的內存。 2000線程是單獨堆棧的4G內存。這不適合32位程序中的2G虛擬內存。 –

+0

@MartinBonner,很好。沒想到這件事,還沒有處理32位的年齡...... – SergeyA

回答

5

看來,Windows上的limitiation的堆棧空間。如果你減少給每個線程的堆棧空間,你可以增加線程的數量。

參考這裏:

https://blogs.msdn.microsoft.com/oldnewthing/20050729-14/?p=34773/

編輯:

剛敲了這個測試程序在我的iMac。在耗盡資源之前設法創建了2047個線程。你的情況可能會有所不同:-)

#include <iostream> 
#include <thread> 
#include <exception> 
#include <stdexcept> 
#include <vector> 


void myvoid() 
{ 
    std::this_thread::sleep_for(std::chrono::seconds(5)); 
} 

void start_thread(std::vector<std::thread>& threads) 
{ 
    try 
    { 
     threads.push_back(std::thread(myvoid)); 
     std::cout << "started " << threads.size() <<"\n"; 
    } 
    catch(...) { 
     std::cout << "failed to start at " << threads.size() + 1 << "\n"; 
     throw; 
    } 
} 

auto main() -> int 
{ 
    std::vector<std::thread> threads; 
    try { 
     for(;;) 
      start_thread(threads); 
    } 
    catch(...) 
    { 

    } 

    for (auto& t : threads) { 
     if (t.joinable()) { 
      t.join(); 
     } 
    } 

    return 0; 
} 

輸出樣本:

... 
started 2042 
started 2043 
started 2044 
started 2045 
started 2046 
started 2047 
failed to start at 2048 
$ 
+0

謝謝你的觀點,但這不值得。不幸的是,我無法滿足用戶的限制。 –

0

因爲沒有人能預料到能夠推出2000多個線程。你的電腦沒有這方面的資源。

有一個簡單的解決方案,這一點 - 使用線程的數量理智。提示 - 除非你有特殊的情況,否則50以上的東西可能是瘋狂的。

+0

這怎麼可能?我可以在Java或.NET中完美啓動2000個線程(使用相同的翻譯方法)。 –

+0

我不是familair。並且對Java的暴露程度非常有限,但沒有系統可以處理2000個真實線程。您從那裏啓動的線程可能不是真正的內核線程。 – SergeyA

+0

那麼,所以沒有任何解決方案? –

0

如果系統耗盡資源而試圖創建所有這些線程然後這條線可能會拋出異常:

 threads.push_back(std::thread(myvoid)); 

這會破壞載體threads,那麼它將調用std::terminate(),因爲它破壞了一個std::thread即可連接。

可以使代碼安全由try塊之前移動threads報關,然後在catch處理程序,確保您加入(或分離)所有的線程。

+0

謝謝你的觀點。你能否做一個例子_確保我加入(或分離)catch handler_中的所有線程? –

+0

您已經在一個循環中加入它們,但如果引發異常,則該代碼將不會運行。您只需確保循環(或類似循環)在引發異常時發生,以在線程銷燬之前將其加入。 –