c ++线程函数说明

时间:2015-10-19 18:52:23

标签: c++ multithreading

#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()将如何处理?

  1. 在主程序的堆栈中是否只有一个thread_fun()副本,其中有5000个线程可以访问它?

  2. 是否会在主程序的堆栈上创建5000份thread_fun()副本,每个帖子都可以访问自己的thread_fun()副本?

  3. thread_fun()加载到5000个线程中的每一个&#39;自己的堆栈而不是主程序堆栈?

  4. 我开始学习c ++线程,并且想知道如何处理这种情况。

4 个答案:

答案 0 :(得分:3)

每个线程都有自己的堆栈,每次线程调用一个函数时,所有局部变量(从堆栈内部调用)和状态都将分别存储在线程堆栈内。

enter image description here

所有全局和动态分配的变量都存储在进程内存的不同部分。注意:永远不要将其称为程序内存,因为内存是在程序成为进程时创建的,我的意思是当程序开始运行时才是创建了这个内存结构(见图)。

现在可能会出现三个问题:

1)如果从线程调用全局变量怎么办?

答案是所有全局数据都存储在&#34;初始化部分&#34;节目记忆。(见图)

2)如果我动态分配一些数据怎么办?

答案是,几乎所有动态分配的内存(使用malloc,new等)都存储在&#34; heap&#34;程序存储器的一部分(见图像)。这个堆部分可以动态增长,因为它不能解决程序在运行时分配多少内存。见图像。在这里,我们的堆可以动态向上。(注意:在某些图表中,堆可能会显示为向下动态增长,但它并不重要。)

3)如何将数据存储在Thread堆栈中并动态分配?

让我们考虑正常的函数调用。当一个程序调用一个函数时,它使用的所有局部变量都存储在&#34; stack&#34;过程记忆的一部分(见图)。这个堆栈动态增长!是的,原因是函数可以执行一些递归调用,并且它独立于我们的程序/输入将执行多少个递归调用。 线程遵循类似的过程。在创建一个线程时,堆栈的某些部分是以&#34;线程堆栈&#34;的形式保留给线程的。在进程内存中(见图)。

现在让我们回答你的问题: 答案1)不。实际上你问他问题的方式是错误的。在主程序&#34;的堆栈中,不会有&#34; thread_fun()的一个副本。 thread_fun()的所有代码都将存储在&#34; text&#34;进程内存的一部分但将被调用5000次。每次由不同的线程调用时,都会创建一个新的线程堆栈,其中存储了局部变量和状态的所有值。 Ans 2)阅读Ans 1 Ans 3)阅读Ans 2:P

请尝试记住并学习图像中的内容并阅读Linux编程接口和http://pages.cs.wisc.edu/~remzi/OSTEP/等书籍,以使您的概念更加强大。希望有所帮助:)

图像取自Linux Programming Interface一书。

答案 1 :(得分:1)

首先,C ++线程在操作系统线程上非常薄(在我看来太薄)层 - 用于Posix系统的pthreads,或用于Windows的Windows线程。问题不在于C ++线程,而在于一般的线程 - 实际上是硬件架构。

  1. 在主程序的堆栈中只有一个thread_fun()副本,其中有5000个线程可以访问它吗?
  2. 这取决于你的意思&#39; stack&#39;。如果你在谈论应用程序堆栈内存,那么问题就没有意义了。函数不在堆栈上分配。函数是代码,实际上代码根本不能以这种方式分配。但是,如果通过&#39; stack&#39;你的意思是“堆栈跟踪”,而不是,5000个线程将产生5000个堆栈跟踪(当用例如pstack这样的例程查看时),并且这5000个堆栈跟踪中的每一个都将包含thread_fun

    1. 是否会在主程序的堆栈上创建5000份thread_fun()副本,每个帖子都可以访问自己的thread_fun()副本?
    2. 见上文。代码永远不会在堆栈上分配。 thread_fun代码只有一个实例。 thread_fun可能有多个不同数据点的实例。

      1. thread_fun()加载到5000个线程中的每个线程中。自己的堆栈而不是主程序堆栈?
      2. 我不明白这个问题。

答案 2 :(得分:0)

对所有这些问题的简短回答是否定的。代码不存储在堆栈中。 thread_fun只有一个副本,它存在于代码段中。操作系统将分配内部数据结构,用于调度cpu上的线程(每个线程的堆栈,线程本地存储,寄存器和指令指针的存储等)。

你拥有的main()堆栈是std :: thread类型的数组。

答案 3 :(得分:0)

正如您所怀疑的那样,将有一个thread_fun副本,它将由并发线程执行。参数化线程函数的常规方法是使用线程函数对象(例如std::bind的返回类型)。

至于5000个线程......你很幸运! 200正在推动大多数系统的限制。如果您需要那么多并发性,那么您将需要研究&#34;异步编程模型&#34;。