はい、各スレッドには独自のスタックがあります。これは非常に必要なことです。スタックは、メソッドが終了した後、メソッドがどこに戻るかを追跡し、戻りアドレスを格納します。各スレッドは独自のコードを実行するため、独自のスタックが必要です。ローカル変数とメソッド引数もそこに格納されるため、(通常は)スレッドセーフになります。
ヒープの数は、より複雑な詳細です。ガベージコレクションされたヒープに対して1を数えています。これは、実装の観点からは完全に正しいわけではありません。3世代のヒープとラージオブジェクトヒープは論理的に異なるヒープであり、合計で4つになります。割り当てが多すぎると、この実装の詳細が重要になります。
マネージコードで完全に無視できないもう1つのものは、静的変数を格納するヒープです。これはAppDomainに関連付けられており、静的変数はAppDomainが存続する限り存続します。.NETの文献では一般的に「ローダーヒープ」と呼ばれています。実際には3つのヒープ(高頻度、低頻度、スタブヒープ)で構成されており、jittedコードと型データもそこに格納されていますが、それは核心に迫っています。
無視リストのさらに下には、ネイティブコードで使用されるヒープがあります。それらのうちの2つは、元帥クラスからすぐに見ることができます。デフォルトのプロセスヒープがあり、Windowsはそこから割り当てます。Marshal.AllocHGlobal()も同様です。また、COMがデータを格納する別のヒープがあり、Marshal.AllocCoTaskMem()がそこから割り当てます。最後に、相互運用するネイティブコードには、ランタイムサポート用の独自のヒープがあります。この種のコードで使用されるヒープの数は、プロセスにロードされるネイティブDLLの数によってのみ制限されます。これらのヒープはすべて存在しますが、直接処理することはほとんどありません。
したがって、最小で10ヒープです。