#include <atomic>
#include <thread>
#include <iostream>
#include <vector>
std::atomic<int> i (0);
void add_one()
{
std::this_thread::sleep_for(std::chrono::seconds(1)); // [1]
++i; // [2]
}
int main()
{
std::vector<std::thread> threads;
while(i < 10)
{
threads.push_back(std::thread(&add_one));
} // [3]
std::cout << "num threads: " << threads.size() << std::endl;
for(auto& t : threads)
{
t.detach();
}
std::cout << "i: " << i << std::endl;
return 0;
}
这段代码有很多错误,我甚至不知道如何开始。最初我只是想让自己相信原子注入真的是原子的。所以我开始构建一些代码来执行此操作。在OSX(使用Clang编译)上运行时,代码将显示“system_error:线程构造函数失败:资源暂时不可用”。视觉工作室在Windows上没有错误。这是由线[1]引起的。如果我将[1]移到[2]之后,则没有错误。
但是我的想法是什么,这[3]应该是一个无限循环!我不知道构造的线程将开始执行它给出的函数。我一直以为是thread.join或thread.detach。有没有办法构造一个线程对象,并告诉它在我想要它开始之前不要做任何事情?
鉴于此,在运行时线程构造函数因为等待时间太长而引发警告并不会让我感到惊讶,但是当我将行[1]移动到[2]之后它为什么会消失]? 当我移动它?
void add_one()
{
++i;
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "blah" << std::endl;
}
Blah永远不会显示,甚至不会以乱码,非线程安全的方式显示。它就像它从未存在过一样。
在窗户上会打印出来。
我很抱歉我面临着巨大的困惑。
答案 0 :(得分:3)
当程序达到某个上限(我的系统上有2048个线程)时,你的程序正在快速创建线程并死掉。当你切换行时它不会失败,因为现在子线程正在递增i,这导致for循环在一切都爆炸之前终止。
你不能在C ++ 11中创建挂起的线程(我不知道为什么。也许他们想要支持那些不支持这种能力的操作系统)。正确的解决方法是在执行任何其他操作之前让线程阻塞某些条件。但是,出于学习目的,像你一样睡了一秒钟就可以了。
答案 1 :(得分:2)
但是为什么当我将[1]行移到[2]之后它会消失?
简单。使用第2行之前的第1行,您将使线程等待一秒钟,然后再增加i
。启动一个线程可能很昂贵,但它不需要接近一秒。您正在创建许多线程,所有这些线程都等待一秒钟到期。当计时器到期时,它们将以原子方式递增i
。在此之前,您的程序正在快速创建越来越多的线程。在任何一个计时器到期之前,您的程序将耗尽资源。
当您在第[2]行之后移动第[1]行时,您的主循环会创建增加i
然后再睡眠的线程。睡眠的唯一影响是将呼叫延迟到detach
。你仍然会创建超过十个线程,但不是更多。