D. Rouse
D. Rouse

Reputation: 49

C++ Error when creating threads in loops

I have a problem when running the following in Visual studio 2015.

#include <thread>
#include <vector>
#include <iostream>
using namespace std;

int main() {

    for (int i = 0; i < 10000; i++) {
        cout << "Loop: " << i << endl;

        vector<thread> threads;
        for (int j = 0; j < 8; j++) {
            try {
                threads.push_back(thread([]() {int a = 4; a++; }));
            }
            catch (const system_error &se) {
                cout << se.what() << endl;
                exit(1);
            }
        }

        for (int j = 0; j < 8; j++) {
            threads.at(j).join();
        }
    }

    return 0;
}

After a few thousand loops have been run the program catches a system_error with the output:

...
3994
3995
3996
3997
3998
resource unavailable try again: resource unavailable try again

I know that there is a maximum number of threads that can be run simultaneously but in this case there's only 8 being run simultaneously after which they're destroyed. Is there a maximum on the total number that can be created?

I have tried running the above on Linux with g++ and it runs fine its only on windows (both visual studio and mingw) that the error occurs. Any help? Thanks.

Upvotes: 2

Views: 1849

Answers (1)

Mgetz
Mgetz

Reputation: 5138

What happened here is best described by understanding how threads are created on windows.

Each thread when it's created is given a default 1Mb stack size. You'll notice you're getting to approximately 3998 threads which would correspond to approximately 3.9Gb of used user address space. This is not an accident, as this corresponds to most of the full 4Gb user address space available to a 32bit process under 64bit windows (Kernel space is 64bit). The extra space is where the executable and necessary system DLLs are getting loaded into.

By changing the build to 64bit you've massively expanded that address space. Having 10000 threads with a 1Mb stack is a drop in a bucket and the limiter becomes non-pagable kernel memory although the 1Mb stacks can and will be paged out causing the system to slow to a crawl.

Upvotes: 5

Related Questions