两个或多个线程如何共享它们已分配的堆上的内存?

时间:2012-08-10 21:06:04

标签: multithreading heap

正如标题所说,两个或多个线程如何共享已分配的堆上的内存?我一直在考虑它,我无法弄清楚他们是如何做到的。以下是我对这个过程的理解,大概我错了。

任何线程都可以通过进行系统调用来添加或删除堆上给定数量的字节,系统调用返回指向此数据的指针,可能是通过写入线程然后可以复制到堆栈的寄存器。 因此,两个线程A和B可以根据需要分配尽可能多的内存。但我没有看到线程A如何知道线程B分配的内存位于何处。我也不知道任何一个线程如何知道其他线程堆栈的位置。多线程程序共享堆,我相信,它可以访问彼此的堆栈,但我无法弄清楚如何。

我尝试搜索这个问题,但只发现了特定于语言的版本,这些版本抽象了细节。

编辑: 我试图不是语言或操作系统特定的,但我正在使用Linux,我正在从低级别的角度看待它,我想是汇编。

5 个答案:

答案 0 :(得分:12)

我对你的问题的解释:线程A如何知道指向内存B的指针正在使用?他们如何交换数据?

答案:它们通常以指向公共内存区域的公共指针开头。这允许他们交换其他数据,包括互相指向其他数据的指针。

示例:

  1. 主线程分配一些共享内存并将其位置存储在p
  2. 主线程启动两个工作线程,将指针p传递给它们
  3. 工作人员现在可以使用p并处理p
  4. 指向的数据

    用真实语言(C#)看起来像这样:

    //start function ThreadProc and pass someData to it
    new Thread(ThreadProc).Start(someData)
    

    线程通常不会访问彼此的堆栈。一切都从传递给线程过程的一个指针开始。


    创建线程是OS功能。它的工作原理如下:

    1. 应用程序使用标准ABI / API
    2. 调用操作系统
    3. 操作系统分配堆栈内存和内部数据结构
    4. OS“伪造”第一个堆栈帧:它将指令指针设置为ThreadProc并将someData“推送”到堆栈上。我说“伪造”因为第一个堆叠框架不是自然产生的,而是由人工操作系统创建的。
    5. 操作系统安排线程。 ThreadProc不知道它已在新堆栈上设置。所有它知道的是someData处于通常的堆栈位置,它会期望它。
    6. 这就是someData到达ThreadProc的方式。这是共享第一个初始数据项的方式。步骤1-3由父线程同步执行。 4发生在子线程上。

答案 1 :(得分:2)

从鸟的视角(1000英里以上)得到一个非常简短的回答:
线程是同一进程的执行路径,并且堆实际上属于进程(并且因此由线程共享)。每个线程只需要自己的堆栈作为一个单独的工作单元。

答案 2 :(得分:0)

如果线程使用相同的堆,则线程可以在堆上共享内存。默认情况下,大多数语言/框架都有一个默认堆,代码可以使用它来从堆中分配内存。在非托管语言中,您通常会进行显式调用以分配堆内存。在C中,例如可能是malloc等。在托管语言中,堆分配通常是自动的,分配的方式取决于语言 - 通常通过使用new运算符。但是,这在很大程度上取决于背景。如果您提供所询问的操作系统或语言环境,我可能会提供更多详细信息。

答案 3 :(得分:0)

与属于同一进程的其他线程共享的线程:其代码部分,数据部分和其他操作系统资源,如打开的文件和信号。

答案 4 :(得分:0)

您缺少的部分是静态内存,其中包含静态变量

在程序启动时分配该内存,并分配已知地址(在链接时确定)。所有地址都可以访问此内存,而无需交换任何数据运行时,因为地址已有效地硬编码。

一个简单的示例可能看起来像这样:

// Global variable.
std::atomic<int> common_var;

void thread1() {
  common_var = compute_some_value();
}

void thread2() {
  do_something();
  int current_value = common_var;
  do_more();
}

当然,全局值可以是一个指针,可以用来交换堆内存。生产者分配一些对象,消费者获取并使用它们。

// Global variable.
std::atomic<bool> produced;
SomeData* data_pointer;

void producer_thread() {
  while (true) {
    if (!produced) {
      SomeData* new_data = new SomeData();
      data_pointer = new_data;
      // Let the other thread know there is something to read.
      produced = true;
    }
  }
}

void consumer_thread() {
  while (true) {
    if (produced) {
      SomeData* my_data = data_pointer;
      data_pointer = nullptr;
      // Let the other thread know we took the data.
      produced = false;
      do_something_with(my_data);
      delete my_data;
    }
  }
}

请注意:这些并不是好的并发代码的示例,但是它们显示了基本思想,没有太多混乱。