スレッドには明確なヒープがありますか?


114

私の知る限り、オペレーティングシステムによってスレッドが作成されると、各スレッドは個別のスタックを取得します。各スレッドはそれ自体に異なるヒープを持っているのでしょうか?


はい、windowsとlinux、cライブラリ

3
いいね。+1それらの基本的な質問が続くようにします。

回答:


128

いいえ。すべてのスレッドが共通のヒープを共有します。

スレッドにはプライベートスタックがあり、アイテムをすばやく追加および削除できます。これにより、スタックベースのメモリが高速になりますが、無限再帰で発生するようにスタックメモリを使いすぎると、スタックオーバーフローが発生します。

すべてのスレッドが同じヒープを共有するため、アロケータ/デアロケータへのアクセスは同期する必要があります。アロケータの競合を回避するためのさまざまなメソッドとライブラリがあります

一部の言語では、メモリのプライベートプール、または単一のスレッドに割り当てることができる個々のヒープを作成できます。


5
通常、スレッドはメモリなどのリソースを共有するので、ブレインデッドでないスレッド実装はすべてヒープを共有します。
R.マルティーニョフェルナンデス

10
主な各スレッドは独自のスタックを持っている理由は...スレッドが実際に(関数呼び出しのような)何かを行うことができるようである
エドモンド

3
各スレッドには個別のスタックがありますが、必ずしも「プライベート」であるとは限りません。他のスレッドは通常、それにアクセスすることができます。
zch

you will get a stack overflow.Stack Overflowでのスタックオーバーフロー!
John Strood、2016年

2
@crisronスレッドごとに個別のヒープを設定することは可能ですが、デフォルトの共有ヒープを使用するのではなく、そのように設定すると、たとえばスレッドAがバッファを割り当て、データを入力して、それをスレッドBに渡すことが難しくなります。 、およびスレッドBにデータを使用させてから、バッファを解放します(スレッドBはスレッドAのヒープにアクセスできないため、スレッドBはバッファを解放できません。スレッドBが実行できる最善の方法は、バッファをスレッドAに戻すことです。もう一度、スレッドAで解放します)。
Jeremy Friesner 2017年

9

デフォルトでは、Cのヒープは1つだけです。

つまり、スレッド対応の一部のアロケータはヒープを分割して、各スレッドが独自の領域を割り当てられるようにします。これにより、ヒープスケールが改善されます。

このようなヒープの1つの例はHoardです。


デフォルトのCおよびC ++では、複数のスレッドはありません。2003年のc ++仕様では、少なくとも仮想マシンの設計でスレッドを許可していないため、c ++のスレッドは実装で定義されています。
Chris Becke、

異なるスレッドがヒープ上から割り当てられる異なる領域を持っている場合でも、別のスレッドによって割り当てられたデータを見ることができるため、スレッドは同じヒープを共有します。
ケンブルーム

1
更新:C ++ 11以降、スレッドは実装で定義されなくなりました。
Michael Dorst、2012

5

OSに依存します。Windowsとunicesの標準Cランタイムは、スレッド間で共有ヒープを使用します。これは、すべてのmalloc / freeをロックすることを意味します。

たとえば、Symbianでは、スレッドごとに独自のヒープが付属していますが、スレッドはどのヒープに割り当てられたデータへのポインタも共有できます。Symbianの設計は、割り当て/解放時のロックの必要性を排除するだけでなく、スレッド間のデータ所有権の明確な仕様を促進するため、私の意見ではより優れています。また、その場合、スレッドが終了すると、スレッドとともに割り当てられたすべてのオブジェクトを取得します。つまり、割り当てられたオブジェクトをリークすることはできません。これは、メモリが制限されたモバイルデバイスで重要なプロパティです。

Erlangも同様の設計に従い、「プロセス」がガベージコレクションの単位として機能します。参照カウントされるバイナリBLOBを除いて、すべてのデータはコピーによってプロセス間で通信されます(私は思う)。


3

各スレッドには独自のスタックと呼び出しスタックがあります。

各スレッドは同じヒープを共有します。


3

それは、「ヒープ」と言うときの正確な意味に依存します。

すべてのスレッドがアドレス空間を共有するため、ヒープに割り当てられたオブジェクトにはすべてのスレッドからアクセスできます。技術的には、スタックはこの意味でも共有されます。つまり、他のスレッドのスタックにアクセスすることを妨げるものは何もありません(そうすることはほとんど意味がありません)。

一方、メモリの割り当てに使用されるヒープ構造があります。ここで、ヒープメモリ割り当てのすべての簿記が行われます。これらの構造は、スレッド間の競合を最小限に抑えるために高度に編成されています。そのため、一部のスレッドはヒープ構造(アリーナ)を共有し、一部のスレッドは別個のアリーナを使用する場合があります。
詳細の優れた説明については、次のスレッドを参照してください。マルチスレッド環境でmallocはどのように機能しますか?


1

通常、スレッドはヒープやその他のリソースを共有しますが、共有しないスレッドのような構造もあります。これらのスレッドのような構造には、Erlangの軽量プロセスと、UNIXの完全なプロセス(への呼び出しで作成fork())があります。また、マルチマシン同時実行に取り組んでいる可能性があります。その場合、スレッド間通信オプションはかなり制限されます。


フォークは、データを新しいメモリの場所にコピーするだけの新しいプロセスを作成するようなものだと思いました。
Jason Tholstrup、

2
fork()は、スレッドも使用できる多くのユースケースで機能します。コピーオンライトのため、Unixシステムでは大きなコストの違いはありません。典型的なユースケースは、ワーカーが他のサービスから(Webサーバーのように)自律的である場合です。別の可能性は、stdin / outを介してメインスレッド/プログラムと通信することです。fork()はUnixでは強力ですが、Windowsなどの他のプラットフォームではスレッド化が優先されます。主な理由は、おそらくfork()を使用する方がはるかに単純で安全であり、Unixにはこの単純さの哲学があるためです。たとえば、スレッドへの移行が遅いapache webserverを参照してください。
ypnos 2009年

1

一般的に言って、すべてのスレッドは同じアドレス空間を使用するため、通常は1つのヒープしかありません。

ただし、少し複雑になる場合があります。スレッドローカルストレージ(TLS)を探しているかもしれませんが、単一の値のみを保存します。

Windows固有:TLSスペースは、TlsAllocを使用して割り当て、TlsFreeを使用して解放できます(概要はこちら)。繰り返しますが、これはヒープではなく、DWORDです。

奇妙なことに、Windows はプロセスごとに複数のヒープをサポートしています。ヒープのハンドルをTLSに保存できます。次に、「スレッドローカルヒープ」のようなものがあります。ただし、ハンドルは他のスレッドには知られていないため、同じアドレス空間であるため、ポインタを使用してメモリにアクセスできます。

編集:一部のメモリアロケーター(具体的にはFreeBSDのjemalloc)は、TLSを使用して「アリーナ」をスレッドに割り当てます。これは、同期のオーバーヘッドを減らすことにより、複数のコアの割り当てを最適化するために行われます。


>「不思議なことに、Windowsはプロセスごとに複数のヒープをサポートします。」これは奇妙なことではありません。割り当ての種類ごとに異なるヒープを使用でき、柔軟性が増すだけです。もちろん、いつでもVirtualAllocにアクセスして、必要に応じて独自のヒープを構築できます。

1

FreeRTOSオペレーティングシステムでは、タスク(スレッド)は同じヒープを共有しますが、それぞれに独自のスタックがあります。これは、低消費電力の低RAMアーキテクチャを扱う場合に非常に便利です。同じメモリプールに複数のスレッドがアクセス/共有できるためですが、これには小さなキャッチが伴うため、開発者はmallocを同期するメカニズムに留意する必要があります。そして、解放が必要です。そのため、セマフォやミューテックスなど、ヒープ上のメモリを割り当てたり解放したりするときに、ある種のプロセス同期/ロックを使用する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.