线程:精细10,崩溃10000

Threads: Fine with 10, Crash with 10000

本文关键字:崩溃 10000 精细 线程      更新时间:2023-10-16

有人能解释一下以下代码崩溃的原因吗:

int a(int x)
{
int s = 0;
for(int i = 0; i < 100; i++)
s += i;
return s;
}
int main()
{
unsigned int thread_no = 10000;
vector<thread> t(thread_no);
for(int i = 0; i < 10; i++)
t[i] = std::thread(a, 10);
for(thread& t_now : t)
t_now.join();
cout << "OK" << endl;
cin.get();
}

但可以使用10个线程我是多线程的新手,根本不明白发生了什么?!

这将创建10000个默认初始化线程的向量:

unsigned int thread_no = 10000;
vector<thread> t(thread_no);

您正在遇到"容量"answers"大小"之间的差异。您不仅创建了一个大到可以容纳10000个线程的向量,还创建了10000个线程的向量。

请参见以下内容(http://ideone.com/i7LBQ6)

#include <iostream>
#include <vector>
struct Foo {
Foo() { std::cout << "Foo()n"; }
};
int main() {
std::vector<Foo> f(8);
std::cout << "f.capacity() = " << f.capacity() << ", size() = " << f.size() << 'n';
}

您只将其中10个元素初始化为运行线程

for(int i = 0; i < 10; i++)
t[i] = std::thread(a, 10);

因此,for循环将看到10个初始化的线程,然后是9990个未启动的线程。

for(thread& t_now : t)
t_now.join();

您可能想尝试使用t.reserve(thread_no);t.emplace_back(a, 10);

下面是一个完整的重命名示例。

int threadFn(int iterations)
{
int s = 0;
for(int i = 0; i < iterations; i++)
s += i;
return s;
}
int main()
{
enum {
MaximumThreadCapacity = 10000,
DesiredInitialThreads = 10,
ThreadLoopIterations = 100,
};
vector<thread> threads;
threads.reserve(MaximumThreadCapacity);
for(int i = 0; i < DesiredInitialThreads; i++)
threads.emplace_back(threadFn, ThreadLoopIterations);
std::cout << threads.size() << " threads spun upn";
for(auto& t : threads) {
t.join();
}
std::cout << "threads joinedn";
}

----编辑----

具体来说,你遇到的崩溃是试图加入一个未运行的线程,http://ideone.com/OuLMyQ

#include <thread>
int main() {
std::thread t;
t.join();
return 0;
}

stderr

terminate called after throwing an instance of 'std::system_error'
what():  Invalid argument

我指出这一点是因为你应该意识到,即使有一个有效的线程,如果你做,也会有竞争条件

if (t.joinable())
t.join();

"t"可能在测试和操作之间变得不可连接。您应该始终在try{}子句中放入一个t.join()。看见http://en.cppreference.com/w/cpp/thread/thread/join

完整示例:

int threadFn(int iterations)
{
int s = 0;
for(int i = 0; i < iterations; i++)
s += i;
return s;
}
int main()
{
enum {
MaximumThreadCapacity = 10000,
DesiredInitialThreads = 10,
ThreadLoopIterations = 100,
};
vector<thread> threads;
threads.reserve(MaximumThreadCapacity);
for(int i = 0; i < DesiredInitialThreads; i++)
threads.emplace_back(threadFn, ThreadLoopIterations);
std::cout << threads.size() << " threads spun upn";
for(auto& t : threads) {
try {
if(t.joinable())
t.join();
} catch (std::system_error& e) {
switch (e.code()) {
case std::errc::invalid_argument:
case std::errc::no_such_process:
continue;
case std::errc::resource_deadlock_would_occur:
std::cerr << "deadlock during join - wth!n";
return e.code();
default:
std::cout << "error during join: " << e.what() << 'n';
return e.code();
}
}
}
std::cout << "threads joinedn";
}

创建一个包含10000个元素的向量,然后填充前十个元素,等待向量中的所有线程加入。您的程序崩溃是因为您忘记设置其他9990。

for(int i = 0; i < 10; i++) // Wrong
for(int i = 0; i < thread_no; i++) // Correct