回答:
いいえ。すべてのスレッドが共通のヒープを共有します。
各スレッドにはプライベートスタックがあり、アイテムをすばやく追加および削除できます。これにより、スタックベースのメモリが高速になりますが、無限再帰で発生するようにスタックメモリを使いすぎると、スタックオーバーフローが発生します。
すべてのスレッドが同じヒープを共有するため、アロケータ/デアロケータへのアクセスは同期する必要があります。アロケータの競合を回避するためのさまざまなメソッドとライブラリがあります。
一部の言語では、メモリのプライベートプール、または単一のスレッドに割り当てることができる個々のヒープを作成できます。
you will get a stack overflow.
Stack Overflowでのスタックオーバーフロー!
デフォルトでは、Cのヒープは1つだけです。
つまり、スレッド対応の一部のアロケータはヒープを分割して、各スレッドが独自の領域を割り当てられるようにします。これにより、ヒープスケールが改善されます。
このようなヒープの1つの例はHoardです。
OSに依存します。Windowsとunicesの標準Cランタイムは、スレッド間で共有ヒープを使用します。これは、すべてのmalloc / freeをロックすることを意味します。
たとえば、Symbianでは、スレッドごとに独自のヒープが付属していますが、スレッドはどのヒープに割り当てられたデータへのポインタも共有できます。Symbianの設計は、割り当て/解放時のロックの必要性を排除するだけでなく、スレッド間のデータ所有権の明確な仕様を促進するため、私の意見ではより優れています。また、その場合、スレッドが終了すると、スレッドとともに割り当てられたすべてのオブジェクトを取得します。つまり、割り当てられたオブジェクトをリークすることはできません。これは、メモリが制限されたモバイルデバイスで重要なプロパティです。
Erlangも同様の設計に従い、「プロセス」がガベージコレクションの単位として機能します。参照カウントされるバイナリBLOBを除いて、すべてのデータはコピーによってプロセス間で通信されます(私は思う)。
それは、「ヒープ」と言うときの正確な意味に依存します。
すべてのスレッドがアドレス空間を共有するため、ヒープに割り当てられたオブジェクトにはすべてのスレッドからアクセスできます。技術的には、スタックはこの意味でも共有されます。つまり、他のスレッドのスタックにアクセスすることを妨げるものは何もありません(そうすることはほとんど意味がありません)。
一方、メモリの割り当てに使用されるヒープ構造があります。ここで、ヒープメモリ割り当てのすべての簿記が行われます。これらの構造は、スレッド間の競合を最小限に抑えるために高度に編成されています。そのため、一部のスレッドはヒープ構造(アリーナ)を共有し、一部のスレッドは別個のアリーナを使用する場合があります。
詳細の優れた説明については、次のスレッドを参照してください。マルチスレッド環境でmallocはどのように機能しますか?
通常、スレッドはヒープやその他のリソースを共有しますが、共有しないスレッドのような構造もあります。これらのスレッドのような構造には、Erlangの軽量プロセスと、UNIXの完全なプロセス(への呼び出しで作成fork()
)があります。また、マルチマシン同時実行に取り組んでいる可能性があります。その場合、スレッド間通信オプションはかなり制限されます。
一般的に言って、すべてのスレッドは同じアドレス空間を使用するため、通常は1つのヒープしかありません。
ただし、少し複雑になる場合があります。スレッドローカルストレージ(TLS)を探しているかもしれませんが、単一の値のみを保存します。
Windows固有:TLSスペースは、TlsAllocを使用して割り当て、TlsFreeを使用して解放できます(概要はこちら)。繰り返しますが、これはヒープではなく、DWORDです。
奇妙なことに、Windows はプロセスごとに複数のヒープをサポートしています。ヒープのハンドルをTLSに保存できます。次に、「スレッドローカルヒープ」のようなものがあります。ただし、ハンドルは他のスレッドには知られていないため、同じアドレス空間であるため、ポインタを使用してメモリにアクセスできます。
編集:一部のメモリアロケーター(具体的にはFreeBSDのjemalloc)は、TLSを使用して「アリーナ」をスレッドに割り当てます。これは、同期のオーバーヘッドを減らすことにより、複数のコアの割り当てを最適化するために行われます。