私の知る限り、各スレッドは、オペレーティングシステムによって作成されたときに個別のスタックを取得します。各スレッドはそれ自体とは異なるヒープを持っているのだろうか?
いいえ。すべてのスレッドは共通のヒープを共有します。
各 スレッドにはプライベートスタックがあります で、アイテムをすばやく追加および削除できます。これにより、スタックベースのメモリが高速になりますが、無限再帰で発生するようなスタックメモリの使用量が多すぎると、スタックオーバーフローが発生します。
すべてのスレッドが同じヒープを共有するため、アロケーター/デアロケーターへのアクセスを同期する必要があります。 allocator contention を回避するためのさまざまなメソッドとライブラリがあります。
一部の言語では、メモリのプライベートプールまたは個々のヒープを作成して、単一のスレッドに割り当てることができます。
デフォルトでは、Cには単一のヒープしかありません。
ただし、スレッドを認識する一部のアロケーターはヒープを分割し、各スレッドが独自の割り当て領域を持つようにします。これにより、ヒープスケールが改善されるはずです。
そのようなヒープの一例は Hoard です。
OSに依存します。 WindowsおよびUnixの標準Cランタイムは、スレッド間で共有ヒープを使用します。これは、すべてのmalloc/freeをロックすることを意味します。
たとえば、Symbianでは、各スレッドに独自のヒープがありますが、スレッドは任意のヒープに割り当てられたデータへのポインターを共有できます。 Symbianの設計は、alloc/free中のロックの必要性を排除するだけでなく、スレッド間のデータ所有権の明確な指定を促進するため、私の意見では優れています。また、その場合、スレッドが死ぬと、スレッドと共に割り当てられたすべてのオブジェクトを取得します。つまり、割り当てたオブジェクトをリークすることはできません。これは、メモリが制限されたモバイルデバイスにある重要なプロパティです。
Erlangは、「プロセス」がガーベッジコレクションの単位として機能する同様の設計に従います。すべてのデータは、コピーによってプロセス間で通信されますが、参照カウントされているバイナリBLOBを除きます(私は思う)。
各スレッドには独自のスタックと呼び出しスタックがあります。
各スレッドは同じヒープを共有します。
「ヒープ」と言ったときの正確な意味に依存します。
すべてのスレッドはアドレス空間を共有するため、ヒープに割り当てられたオブジェクトはすべてのスレッドからアクセス可能です。技術的には、スタックもこの意味で共有されます。つまり、他のスレッドのスタックにアクセスすることを妨げるものは何もありません(そうすることはほとんど意味がありませんが)。
一方、メモリの割り当てに使用されるヒープstructuresがあります。ここで、ヒープメモリの割り当てに関するすべての簿記が行われます。これらの構造は、スレッド間の競合を最小限に抑えるために高度に編成されています。そのため、一部のスレッドはヒープ構造(アリーナ)を共有し、別のスレッドは別個のアリーナを使用します。
詳細の優れた説明については、次のスレッドを参照してください。 マルチスレッド環境でmallocはどのように機能しますか?
一般的に、すべてのスレッドは同じアドレス空間を使用するため、通常はヒープが1つしかありません。
ただし、もう少し複雑になります。 Thread Local Storage (TLS)を探しているかもしれませんが、単一の値のみを保存しています。
Windows固有:TLSスペースは TlsAlloc を使用して割り当てられ、 TlsFree (概要 here )を使用して解放できます。繰り返しますが、それはヒープではなく、DWORDです。
奇妙なことに、Windowsはプロセスごとに複数の ヒープ をサポートしています。ヒープのハンドルをTLSに保存できます。次に、「スレッドローカルヒープ」のようなものがあります。ただし、ハンドルだけが他のスレッドに知られていないため、同じアドレス空間であるため、ポインタを使用してメモリにアクセスできます。
[〜#〜] edit [〜#〜]:一部のメモリアロケータ(具体的にはFreeBSDでは jemalloc )はTLSを使用して割り当てますスレッドへの「アリーナ」。これは、同期オーバーヘッドを削減することにより、複数のコアの割り当てを最適化するために行われます。
通常、スレッドはヒープと他のリソースを共有しますが、共有しないスレッドのような構造があります。これらのスレッドのような構造には、Erlangの軽量プロセスと、UNIXの完全なプロセス(fork()
の呼び出しで作成された)があります。また、マルチマシン並行性に取り組んでいる場合もあります。その場合、スレッド間通信オプションはかなり制限されます。
FreeRTOSオペレーティングシステムでは、タスク(スレッド)は同じヒープを共有しますが、それぞれが独自のスタックを持っています。これは、低消費電力low RAMアーキテクチャを扱う場合に非常に便利です。複数のスレッドが同じメモリプールにアクセス/共有できるため、開発者は小さなキャッチを必要とします。 mallocとfreeを同期するためのメカニズムが必要であることに注意してください。そのため、ヒープ上のメモリを割り当てたり解放したりするときに、セマフォやミューテックスなどの何らかのタイプのプロセス同期/ロックを使用する必要があります。