回答:
プロセスとスレッドはどちらも独立した実行シーケンスです。典型的な違いは、(同じプロセスの)スレッドが共有メモリ空間で実行されるのに対し、プロセスは個別のメモリ空間で実行されることです。
どの「ハードウェア」スレッドと「ソフトウェア」スレッドを参照しているのかわかりません。スレッドは、CPU機能ではなくオペレーティング環境機能です(CPUには通常、スレッドを効率化する操作があります)。
Erlangは共有メモリマルチプログラミングモデルを公開しないため、「プロセス」という用語を使用します。それらを「スレッド」と呼ぶことは、それらがメモリを共有していることを意味します。
プロセス
各プロセスは、プログラムの実行に必要なリソースを提供します。プロセスには、仮想アドレス空間、実行可能コード、システムオブジェクトへのオープンハンドル、セキュリティコンテキスト、一意のプロセス識別子、環境変数、優先度クラス、最小および最大のワーキングセットサイズ、および少なくとも1つの実行スレッドがあります。各プロセスは、通常プライマリスレッドと呼ばれる単一のスレッドで開始されますが、そのスレッドのいずれかから追加のスレッドを作成できます。
スレッド
スレッドは、実行をスケジュールできるプロセス内のエンティティです。プロセスのすべてのスレッドは、仮想アドレス空間とシステムリソースを共有します。さらに、各スレッドは、例外ハンドラー、スケジューリング優先順位、スレッドローカルストレージ、一意のスレッド識別子、およびスケジュールされるまでスレッドコンテキストを保存するためにシステムが使用する一連の構造を維持します。スレッドコンテキストには、スレッドのマシンレジスタのセット、カーネルスタック、スレッド環境ブロック、およびスレッドのプロセスのアドレス空間内のユーザースタックが含まれます。スレッドは、クライアントを偽装するために使用できる独自のセキュリティコンテキストを持つこともできます。
この情報は、ここのMicrosoft Docsで見つかりました:プロセスとスレッドについて
Microsoft Windowsは、プリエンプティブマルチタスクをサポートしています。これにより、複数のプロセスから複数のスレッドを同時に実行する効果が生まれます。マルチプロセッサコンピュータでは、システムは、コンピュータ上のプロセッサと同じ数のスレッドを同時に実行できます。
処理する:
糸:
まず、理論的な側面を見てみましょう。プロセスとスレッドの違い、およびそれらの間で共有されるものを理解するには、プロセスが概念的に何であるかを理解する必要があります。
私たちは、セクションから、次のしている2.2.2古典スレッドモデルで現代的なオペレーティングシステムの3Eタネンバウムによって:
プロセスモデルは、リソースのグループ化と実行という2つの独立した概念に基づいています。それらを分離すると便利な場合があります。ここがスレッドの出番です...
彼は続けます:
プロセスを見る1つの方法は、関連するリソースをグループ化する方法であるということです。プロセスには、プログラムテキストとデータ、およびその他のリソースを含むアドレススペースがあります。これらのリソースには、開いているファイル、子プロセス、保留中のアラーム、シグナルハンドラー、アカウンティング情報などが含まれます。それらをプロセスの形でまとめることにより、より簡単に管理できます。プロセスが持つもう1つの概念は、実行のスレッドであり、通常はスレッドだけに短縮されます。スレッドには、次に実行する命令を追跡するプログラムカウンターがあります。現在の作業変数を保持するレジスタがあります。実行履歴を含むスタックがあり、呼び出されたがまだ返されていないプロシージャごとに1つのフレームがあります。スレッドは何らかのプロセスで実行する必要がありますが、スレッドとそのプロセスは異なる概念であり、個別に処理できます。プロセスは、リソースをグループ化するために使用されます。スレッドは、CPUでの実行がスケジュールされているエンティティです。
さらに下には、次の表があります。
Per process items | Per thread items
------------------------------|-----------------
Address space | Program counter
Global variables | Registers
Open files | Stack
Child processes | State
Pending alarms |
Signals and signal handlers |
Accounting information |
ハードウェアマルチスレッドの問題に対処しましょう。古典的には、CPUは単一の実行スレッドをサポートし、単一のプログラムカウンターとレジスタのセットを介してスレッドの状態を維持します。しかし、キャッシュミスがあるとどうなりますか?メインメモリからデータをフェッチするには長い時間がかかりますが、その間、CPUはアイドル状態になっています。したがって、誰かが基本的に2組のスレッド状態(PC +レジスター)を持ち、別のスレッドが(おそらく同じプロセス内、異なるプロセス内の)スレッドがメインメモリで待機している間に作業を完了できるようにするという考えを持っていました。この概念には、ハイパースレッディングや同時マルチスレッディング(略してSMT)など、複数の名前と実装があります。
次にソフトウェア側を見てみましょう。スレッドをソフトウェア側で実装するには、基本的に3つの方法があります。
スレッドを実装するために必要なのは、CPU状態を保存し、複数のスタックを維持する機能だけです。これは、多くの場合、ユーザー空間で実行できます。ユーザー空間スレッドの利点は、カーネルにトラップする必要がないため、スレッドの切り替えが非常に高速であり、スレッドを好きなようにスケジュールできることです。最大の欠点は、ブロックI / O(プロセス全体とそのすべてのユーザースレッドをブロックする)を実行できないことです。これは、そもそもスレッドを使用する大きな理由の1つです。スレッドを使用してI / Oをブロックすると、多くの場合、プログラムの設計が大幅に簡略化されます。
カーネルスレッドには、スケジューリングの問題をすべてOSに任せることに加えて、ブロッキングI / Oを使用できるという利点があります。ただし、各スレッドの切り替えにはカーネルへのトラップが必要であり、これは潜在的に比較的低速です。ただし、I / Oのブロックが原因でスレッドを切り替えている場合は、I / O操作によっておそらく既にカーネルにトラップされているため、これは実際には問題にはなりません。
別のアプローチは、それぞれを複数のユーザースレッドを持つ複数のカーネルスレッドで2つを組み合わせる方法です。
したがって、用語の質問に戻ると、プロセスと実行のスレッドは2つの異なる概念であり、どの用語を使用するかの選択は、話している内容によって異なることがわかります。「軽量プロセス」という用語については、「実行のスレッド」という用語だけでなく、実際に何が行われているのかを実際に伝えるものではないため、個人的にはその点を理解していません。
並行プログラミングに関してさらに説明する
プロセスには自己完結型の実行環境があります。プロセスには通常、基本的なランタイムリソースの完全なプライベートセットがあります。特に、各プロセスには独自のメモリ空間があります。
スレッドはプロセス内に存在します—すべてのプロセスには少なくとも1つあります。スレッドは、メモリや開いているファイルなど、プロセスのリソースを共有します。これにより、効率的ですが潜在的に問題のあるコミュニケーションが可能になります。
平均的な人を念頭に置いて、
コンピューターで、Microsoft WordとWebブラウザーを開きます。これらを2つのプロセスと呼びます。
Microsoftの言葉では、何かを入力すると、自動的に保存されます。これで、編集と保存が並行して行われることがわかります。1つのスレッドで編集し、他のスレッドで保存します。
アプリケーションは、1つ以上のプロセスで構成されます。プロセスは、簡単に言えば、実行プログラムです。1つ以上のスレッドがプロセスのコンテキストで実行されます。スレッドは、オペレーティングシステムがプロセッサ時間を割り当てる基本単位です。スレッドは、別のスレッドによって現在実行されている部分を含め、プロセスコードの任意の部分を実行できます。ファイバーは、アプリケーションによって手動でスケジュールする必要がある実行の単位です。ファイバーは、ファイバーをスケジュールするスレッドのコンテキストで実行されます。
処理する:
例:
ブラウザーを開きます(mozilla、Chrome、IE)。この時点で、新しいプロセスの実行が開始されます。
スレッド:
例:
ブラウザで複数のタブを開く。
スレッドとプロセスはどちらも、OSリソース割り当てのアトミック単位です(つまり、CPU時間をそれらの間でどのように分割するかを記述する同時実行モデルと、他のOSリソースを所有するモデルがあります)。違いがあります:
上記のGreg Hewgillは、「プロセス」という単語のErlangの意味については正しかったです。ここでは、Erlangがプロセスを軽量にできる理由について説明します。
プロセスとスレッドはどちらも独立した実行シーケンスです。典型的な違いは、(同じプロセスの)スレッドが共有メモリ空間で実行されるのに対し、プロセスは個別のメモリ空間で実行されることです。
処理する
実行中のプログラムです。テキストセクション、つまりプログラムコード、プログラムカウンタの値とプロセッサレジスタの内容で表される現在のアクティビティがあります。また、一時データ(関数パラメーター、戻りアドレス指定変数、ローカル変数など)を含むプロセススタックと、グローバル変数を含むデータセクションも含まれます。プロセスにはヒープも含まれます。ヒープは、プロセスの実行時に動的に割り当てられるメモリです。
糸
スレッドは、CPU使用率の基本単位です。スレッドID、プログラムカウンター、レジスタセット、スタックで構成されます。同じプロセスに属する他のスレッド、コードセクション、データセクション、およびオープンファイルやシグナルなどの他のオペレーティングシステムリソースと共有しました。
-Galvinがオペレーティングシステムから取得
http://lkml.iu.edu/hypermail/linux/kernel/9608/0191.html
Linus Torvalds(torvalds@cs.helsinki.fi)
1996年8月6日火曜日12:47:31 +0300(EET DST)
メッセージの並べ替え:[日付] [スレッド] [件名] [作成者]
次のメッセージ:Bernd P. Ziller: "Re:Oops in get_hash_table"
前のメッセージ:Linus Torvalds:「Re:I / O要求の順序付け」
1996年8月5日月曜日、ピーターP.アイゼルローは次のように書いています。
スレッドの概念を明確に保つ必要があります。スレッドがプロセスと混同されている人が多すぎるようです。次の議論はLinuxの現在の状態を反映しているのではなく、高レベルの議論に留まるための試みです。
番号!
「スレッド」と「プロセス」が別個のエンティティであると考える理由はありません。それが伝統的に行われているやり方ですが、個人的にはそのように考えるのは大きな間違いだと思います。そのように考える唯一の理由は歴史的な手荷物です。
スレッドとプロセスはどちらも、「実行のコンテキスト」という1つの要素にすぎません。異なるケースを人工的に区別しようとすることは、自己制限的です。
ここでCOEと呼ばれる「実行のコンテキスト」は、そのCOEのすべての状態の集まりにすぎません。その状態には、CPUの状態(レジスタなど)、MMUの状態(ページマッピング)、アクセス許可の状態(uid、gid)、さまざまな「通信状態」(開いているファイル、シグナルハンドラなど)が含まれます。従来、「スレッド」と「プロセス」の違いは、主にスレッドにCPU状態(および他の最小限の状態)があることですが、他のすべてのコンテキストはプロセスに由来します。ただし、これは1つだけです はCOEの全体の状態を分割する方法にすぎず、それを行う正しい方法であると言っていることはありません。自分をそのようなイメージに制限するのは、まったくばかげています。
Linuxがこれについて(そして私が物事を機能させたい方法で)考えている方法は、「プロセス」や「スレッド」といったものは存在しないということです。COE(Linuxでは「タスク」と呼ばれます)の全体しかありません。異なるCOEは、コンテキストの一部を互いに、および1つのサブセットで共有できます。、その共有のは従来の「スレッド」/「プロセス」設定ですが、それは実際にはサブセットとしてのみ見なされます(重要なサブセットですが、その重要性は設計からではなく、標準から:Linuxの上で標準に準拠したスレッドプログラムも実行したいのです。
つまり、スレッド/プロセスの考え方を中心に設計しないでください。カーネルはCOEの考え方に基づいて設計し、次にpthreads ライブラリを設計する必要があります。は、制限されたpthreadインターフェースを、COEのその見方を使用したいユーザーにエクスポートできます。
スレッド/プロセスではなくCOEを考えると、何が可能になるかの例と同じです。
- 外部「cd」プログラムを実行できます。これは、UNIXおよび/またはプロセス/スレッドでは従来不可能でした(愚かな例ですが、従来のUNIXに限定されないこれらの種類の「モジュール」を使用できるという考え方です) / threads setup)。次を実行します。
clone(CLONE_VM | CLONE_FS);
子:execve( "external-cd");
/ *「execve()」はVMの関連付けを解除するため、CLONE_VMを使用した唯一の理由は、クローン作成の動作を高速化することでした* /
- 自然に "vfork()"を実行できます(最小限のカーネルサポートを意味しますが、そのサポートはCUAの考え方に完全に適合します)。
clone(CLONE_VM);
子:実行し続け、最終的にexecve()
母:execveを待つ
- 外部の「IOデーモン」を実行できます。
clone(CLONE_FILES);
子:ファイル記述子などを開く
母:fdの子を開いてvvを使用します。
上記のすべてが機能するのは、スレッド/プロセスの考え方に縛られないためです。たとえば、CGIスクリプトが「実行のスレッド」として実行されるWebサーバーを考えてみてください。従来のスレッドは常にアドレス空間全体を共有する必要があるため、これを従来のスレッドで行うことはできません。そのため、Webサーバー自体で実行したいすべてのものをリンクする必要があります(「スレッド」は実行できません)。別の実行可能ファイル)。
例えば、共有の「コンテキストの実行」問題としてこのの思考の代わりに、あなたのタスクは今、外部プログラムを実行することにしました(=親からアドレス空間を分離する)ことができるなど、彼らがしたい場合、またはそれらをすることができ、親を持つすべてのものを除くためファイル記述子(サブ「スレッド」が親が心配する必要なく多くのファイルを開くことができるように:サブ「スレッド」が終了すると自動的に閉じ、親のfdを使い果たしません) 。
たとえば、スレッド化された「inetd」を考えてみてください。オーバーヘッドの低いfork + execが必要なので、Linuxの方法では、「fork()」を使用する代わりに、マルチスレッドのinetdを作成します。各スレッドはCLONE_VM(アドレス空間を共有しますが、ファイルを共有しません)記述子など)。次に、子は、それが外部サービス(rlogindなど)である場合、または内部inetdサービス(echo、timeofday)のいずれかである場合に実行できます。
「スレッド」/「プロセス」ではそれはできません。
ライナス
LinuxカーネルのOSビューからそれに答えようとする
プログラムをメモリに起動すると、プロセスになります。プロセスには独自のアドレス空間があり.text
、コンパイル済みコードを格納するセグメント、.bss
初期化されていない静的変数またはグローバル変数を格納するセグメントなど、メモリ内にさまざまなセグメントがあります。
各プロセスには、独自のプログラムカウンターとユーザー空間スタックがあります。
カーネル内では、各プロセスは独自のカーネルスタック(セキュリティの問題のためにユーザー空間スタックから分離されています)と、task_struct
一般にプロセス制御ブロックとして抽象化された名前付きの構造を持ち、優先順位や状態などのプロセスに関するすべての情報を格納します、(そして他の多くのチャンク)。
プロセスは複数の実行スレッドを持つことができます。
スレッドに入ると、それらはプロセス内に常駐し、ファイルシステムリソース、保留中の信号の共有、データ(変数と命令)の共有などのスレッド作成中に渡すことができる他のリソースと親プロセスのアドレス空間を共有するため、スレッドが軽量になり、したがって、より高速なコンテキスト切り替えが可能になります。
カーネル内部では、各スレッドはtask_struct
、スレッドを定義する構造とともに、独自のカーネルスタックを持っています。したがって、カーネルは同じプロセスのスレッドを異なるエンティティと見なし、それ自体でスケジュール可能です。同じプロセス内のスレッドは、スレッドグループid(tgid
)と呼ばれる共通のIDを共有します。また、プロセスID(pid
)と呼ばれる一意のIDを持っています。
Javaの世界に関するこの質問に答えようとしています。
プロセスはプログラムの実行ですが、スレッドはプロセス内の単一の実行シーケンスです。プロセスには複数のスレッドを含めることができます。スレッドは、軽量プロセスと呼ばれることもあります。
例えば:
例1:JVMは単一のプロセスで実行され、JVMのスレッドはそのプロセスに属するヒープを共有します。そのため、複数のスレッドが同じオブジェクトにアクセスする場合があります。スレッドはヒープを共有し、独自のスタックスペースを持っています。これは、1つのスレッドによるメソッドの呼び出しとそのローカル変数が他のスレッドからスレッドセーフに保たれる方法です。ただし、ヒープはスレッドセーフではなく、スレッドセーフのために同期する必要があります。
例2:プログラムは、キーストロークを読み取って絵を描くことができない場合があります。プログラムはキーボード入力に最大限の注意を払う必要があり、一度に複数のイベントを処理する機能がないと問題が発生します。この問題の理想的な解決策は、プログラムの2つ以上のセクションを同時にシームレスに実行することです。スレッドを使用すると、これを行うことができます。ここで、絵を描くことはプロセスであり、キーストロークを読むことはサブプロセス(スレッド)です。
プロセスはアプリケーションの実行インスタンスであり、スレッドはプロセス内の実行パスです。また、プロセスには複数のスレッドを含めることができます。スレッドは、プロセスが実行できるすべてのことを実行できることに注意してください。ただし、プロセスは複数のスレッドで構成できるため、スレッドは「軽量」プロセスと見なすことができます。したがって、スレッドとプロセスの本質的な違いは、それぞれが達成するために使用される作業です。スレッドは小さなタスクに使用されますが、プロセスはより「重い」タスク(基本的にはアプリケーションの実行)に使用されます。
スレッドとプロセスのもう1つの違いは、同じプロセス内のスレッドは同じアドレス空間を共有するのに対し、異なるプロセスは共有しないことです。これにより、スレッドは同じデータ構造と変数を読み書きでき、スレッド間の通信も容易になります。プロセス間の通信(IPCまたはプロセス間通信とも呼ばれます)は、非常に難しく、リソースを大量に消費します。
スレッドとプロセスの違いの概要は次のとおりです。
スレッドは個別のアドレス空間を必要としないため、プロセスよりも作成が簡単です。
スレッドは、一度に1つのスレッドのみが変更する必要があるデータ構造を共有するため、マルチスレッドでは注意深いプログラミングが必要です。スレッドとは異なり、プロセスは同じアドレス空間を共有しません。
スレッドは、プロセスよりもはるかに少ないリソースを使用するため、軽量と見なされます。
プロセスは互いに独立しています。スレッドは、同じアドレス空間を共有するため相互に依存しているため、異なるスレッドが相互に踏み込まないように注意する必要があります。
これは、上記の#2を説明する別の方法です。
プロセスは複数のスレッドで構成できます。
以下は、コードプロジェクトに関する記事の1つから得たものです。必要なものがすべて明確に説明されていると思います。
スレッドは、ワークロードを個別の実行ストリームに分割するもう1つのメカニズムです。スレッドはプロセスよりも軽量です。つまり、完全なプロセスよりも柔軟性は低くなりますが、オペレーティングシステムの設定が少ないため、より早く開始できます。プログラムが2つ以上のスレッドで構成される場合、すべてのスレッドが単一のメモリ空間を共有します。プロセスには個別のアドレス空間が与えられます。すべてのスレッドが単一のヒープを共有します。ただし、各スレッドには独自のスタックが与えられます。
処理する:
プロセスは基本的に実行中のプログラムです。アクティブなエンティティです。一部のオペレーティングシステムでは、「タスク」という用語を使用して、実行中のプログラムを指します。プロセスは常に、メインメモリまたはランダムアクセスメモリとも呼ばれるメインメモリに格納されます。したがって、プロセスはアクティブなエンティティと呼ばれます。マシンを再起動すると消えます。複数のプロセスが同じプログラムに関連付けられている場合があります。マルチプロセッサシステムでは、複数のプロセスを並行して実行できます。ユニプロセッサシステムでは、真の並列処理は実現されませんが、プロセススケジューリングアルゴリズムが適用され、プロセッサは各プロセスを一度に1つずつ実行するようにスケジュールされ、同時実行性の錯覚が生じます。例:「電卓」プログラムの複数のインスタンスを実行します。各インスタンスはプロセスと呼ばれます。
糸:
スレッドはプロセスのサブセットです。実際のプロセスに似ていますが、プロセスのコンテキスト内で実行され、カーネルによってプロセスに割り当てられた同じリソースを共有するため、「軽量プロセス」と呼ばれます。通常、プロセスには1つの制御スレッドしかありません。一度に実行されるマシン命令のセットは1つだけです。プロセスは、命令を同時に実行する複数の実行スレッドで構成することもできます。複数の制御スレッドは、マルチプロセッサシステムで可能な真の並列処理を利用できます。ユニプロセッサシステムでは、スレッドスケジューリングアルゴリズムが適用され、プロセッサは各スレッドを一度に1つずつ実行するようにスケジュールされます。プロセス内で実行されているすべてのスレッドは、同じアドレス空間、ファイル記述子、スタック、およびその他のプロセス関連の属性を共有します。プロセスのスレッドは同じメモリを共有するため、
ref- https://practice.geeksforgeeks.org/problems/difference-between-process-and-thread
インタビュアーの観点から見ると、プロセスのように複数のスレッドを持つことができるという明らかなものに加えて、聞きたいのは基本的に3つだけです。
さらに詳しく知りたい場合は、Scott Langhamの応答でほぼすべてをカバーできます。これらはすべて、オペレーティングシステムの観点からのものです。異なる言語は、タスク、軽量スレッドなどの異なる概念を実装できますが、それらは(Windowsのファイバーの)スレッドを使用するための単なる方法です。ハードウェアとソフトウェアのスレッドはありません。ハードウェアとソフトウェアの例外と割り込み、またはユーザーモードとカーネルスレッドがあります。
視覚化して学習に慣れている方のために、ここにプロセスとスレッドを説明するために作成した便利な図を示します。
MSDNの情報を使用しました- プロセスとスレッドについて
組み込みの世界から来て、プロセスの概念は、 MMU(メモリ管理ユニット)を備えた「ビッグ」プロセッサ(デスクトップCPU、ARM Cortex A-9)、およびMMUの使用をサポートするオペレーティングシステム(Linuxなど)。小さい/古いプロセッサとマイクロコントローラ、およびfreeRTOSなどの小さいRTOSオペレーティングシステム(リアルタイムオペレーティングシステム)では、MMUのサポートはなく、プロセスはなくスレッドのみです。
スレッドは相互にメモリにアクセスでき、OSによってインターリーブ方式でスケジュールされるため、並列に実行されているように見えます(またはマルチコアでは実際に並列に実行されているように見えます)。
一方、プロセスは、MMUによって提供および保護される仮想メモリのプライベートサンドボックスにあります。これは次のことを可能にするので便利です。
残念ながら、私はそこでほとんどすべての回答を熟読しましたが、現在、OSコースを受講している学部生として、2つの概念を完全に理解することはできません。ほとんどの人がいくつかのOSの本を読んでいるということを意味します。つまり、スレッドはプロセスのアドレス空間を利用するため、トランザクションユニットのグローバル変数にアクセスできます。しかし、なぜプロセスが存在するのかという新たな疑問が生じます。認識的には、スレッドはプロセスと比べてより軽量であることがわかっています。以前の回答の1つから抜粋した画像を利用して、次の例を見てみましょう。
Libre Officeのように、3つのスレッドが同時にワードドキュメントで作業しています。1つ目は、単語にスペルミスがある場合に下線を引くことでスペルチェックを行います。2番目は、キーボードから文字を受け取り、印刷します。そして最後は、何かがうまくいかなくても作業中のドキュメントを失わないように、短い時間ごとにドキュメントを保存します。この場合、3つのスレッドは3つのプロセスになることはできません。これらのスレッドは、プロセスのアドレス空間である共通メモリを共有し、編集中のドキュメントにすべてアクセスできるためです。つまり、道はスレッドである2つのブルドーザーと1つの画像には欠けていますが、ワードドキュメントです。
マルチスレッドを組み込んだPython(解釈言語)でアルゴリズムを構築しているときに、以前に構築した逐次アルゴリズムと比較して実行時間が良くないことに驚きました。この結果の理由を理解するために、いくつか読んで、マルチスレッドとマルチプロセスの違いをよりよく理解するための興味深いコンテキストが得られたと考えています。
マルチコアシステムは複数の実行スレッドを実行する可能性があるため、Pythonはマルチスレッドをサポートする必要があります。しかし、Pythonはコンパイルされた言語ではなく、インタープリター言語です1。つまり、プログラムは実行するために解釈する必要があり、インタープリターは実行を開始する前にプログラムを認識しません。ただし、Pythonのルールがわかっているため、それらのルールを動的に適用します。その場合、Pythonでの最適化は、実行されるコードではなく、主にインタープリター自体の最適化でなければなりません。これは、C ++などのコンパイルされた言語とは対照的で、Pythonのマルチスレッドに影響を与えます。具体的には、Pythonはグローバルインタープリターロックを使用してマルチスレッドを管理します。
一方、コンパイル済み言語はコンパイル済みです。プログラムは「完全に」処理されます。最初にその構文定義に従って解釈され、次に言語に依存しない中間表現にマップされ、最後に実行可能コードにリンクされます。このプロセスでは、コンパイル時にすべて利用できるため、コードを高度に最適化できます。さまざまなプログラムの相互作用と関係は、実行可能ファイルの作成時に定義され、最適化に関する強力な決定を行うことができます。
現代の環境では、Pythonのインタープリターはマルチスレッドを許可する必要があり、これは安全かつ効率的でなければなりません。これが、インタープリター型言語とコンパイル型言語の違いの要点です。インタープリターは、異なるスレッドからの内部共有データを妨害してはならず、同時に計算のためのプロセッサーの使用を最適化する必要があります。
以前の投稿で述べたように、プロセスとスレッドはどちらも独立した順次実行です。主な違いは、プロセスの複数のスレッド間でメモリが共有されるのに対し、プロセスはメモリ空間を分離することです。
Pythonでは、データはグローバルインタープリターロックによって異なるスレッドによる同時アクセスから保護されます。どのPythonプログラムでも、一度に実行できるスレッドは1つだけです。一方、各プロセスのメモリは他のプロセスから分離され、複数のコアでプロセスを実行できるため、複数のプロセスを実行できます。
1ドナルド・クヌースは、The Art of Computer Programming:Fundamental Algorithmsの解釈ルーチンについて説明しています。
同じプロセス内のスレッドはメモリを共有しますが、各スレッドには独自のスタックとレジスタがあり、スレッドはスレッド固有のデータをヒープに格納します。スレッドは独立して実行されることはないため、スレッド間通信はプロセス間通信に比べてはるかに高速です。
プロセスが同じメモリを共有することはありません。子プロセスが作成すると、親プロセスのメモリ位置が複製されます。プロセス通信は、パイプ、共有メモリ、およびメッセージ解析を使用して行われます。スレッド間のコンテキスト切り替えは非常に遅いです。
これまでに見つけた最良の答えは、Michael Kerriskの「The Linux Programming Interface」です。
最近のUNIX実装では、各プロセスが複数の実行スレッドを持つことができます。スレッドを想定する1つの方法は、同じ仮想メモリを共有する一連のプロセスと、他のさまざまな属性としてです。各スレッドは同じプログラムコードを実行しており、同じデータ領域とヒープを共有しています。ただし、各スレッドには、ローカル変数と関数呼び出しリンケージ情報を含む独自のスタックがあります。[LPI 2.12]
この本は素晴らしい明快さの源です。Julia Evansさんは、この記事でLinuxグループが実際にどのように機能するかを明らかにするのに役立つと述べました。
例1:JVMは単一のプロセスで実行され、JVMのスレッドはそのプロセスに属するヒープを共有します。そのため、複数のスレッドが同じオブジェクトにアクセスする場合があります。スレッドはヒープを共有し、独自のスタックスペースを持っています。これは、1つのスレッドによるメソッドの呼び出しとそのローカル変数が他のスレッドからスレッドセーフに保たれる方法です。ただし、ヒープはスレッドセーフではなく、スレッドセーフのために同期する必要があります。
それらはほとんど同じですが、主な違いは、スレッドが軽量であり、プロセスがコンテキストの切り替えや作業負荷などの面で重いことです。