Go 言語の同時実行の仕組みは非常に使いやすく、同時実行の開始方法に言語レベルのキーワードを直接追加することで実現でき、他のプログラミング言語に比べて軽量です。
以下にいくつかの概念を示します。
プロセス/スレッド
プロセスは、オペレーティング システムにおけるプログラムの実行プロセスであり、システムによるリソースの割り当てとスケジューリングのための独立した単位です。
スレッドとは、プロセスの実行主体であり、CPU のスケジューリングやディスパッチの基本単位であり、プロセスよりも小さく、独立して実行できる基本単位です。
プロセスは複数のスレッドを作成およびキャンセルでき、同じプロセス内の複数のスレッドを同時に実行できます。
同時/並列
シングルコア CPU 上で実行されるマルチスレッド プログラムは並行と呼ばれ、マルチコア CPU 上で実行されるマルチスレッド プログラムは並列と呼ばれます。
同時実行は並列処理と同じではありません。同時実行は主にタイム スライスを切り替えて「同時」操作を実現することによって実現されますが、並列処理はマルチコアを直接使用してマルチスレッド操作を実現します。Go プログラムは、実行に使用するコアの数を設定できます。マルチコアコンピュータの機能を活用します。
コルーチン/スレッド
コルーチン: 独立したスタック領域、共有ヒープ領域、スケジューリングはユーザーによって制御されます。これは本質的にユーザーレベルのスレッドに似ており、これらのユーザーレベルのスレッドのスケジューリングもそれ自体で実装されます。
スレッド: 複数のコルーチンを 1 つのスレッドで実行でき、コルーチンは軽量のスレッドです。
エレガントな同時プログラミング パラダイム、完璧な同時サポート、優れた同時パフォーマンスは、他の言語と区別する Go 言語の主な特徴です。 Go 言語を使用してサーバー プログラムを開発する場合は、その同時実行メカニズムを深く理解する必要があります。
ゴルーチンの概要
Goroutine は、単一プロセスで数千の同時タスクを実行できる非常に軽量な実装であり、Go 言語の同時実行設計の中核です。
結局のところ、ゴルーチンは実際にはスレッドですが、スレッドよりも小さく、十数個のゴルーチンが最下層の 5 ~ 6 個のスレッドに反映されることもありますし、Go 言語はゴルーチン間のメモリ共有も実現します。
go キーワードを使用して goroutine を作成し、呼び出される関数の前に go 宣言を置き、同じアドレス空間でこの関数を呼び出して実行すると、関数は独立した同時スレッドとして実行されます。 Go言語はゴルーチンと呼ばれます。
goroutineの使い方は以下の通りです。
//goキーワードを使用して、メソッドの呼び出し前に新しいgoroutineを作成し、メソッド本体を実行します
go GetThingDone(param1、param2);
//無名のメソッドを作成し、実行します
go func(param1、param2) {
}(val1、val2)
//直接goroutineを作成し、goroutine内でコードブロックを実行します
go {
//何かをして...
}
ゴルーチンはマルチコア CPU 環境で並列化されるため、コード ブロックが複数のゴルーチンで実行される場合、コードの並列性が達成されます。
プログラムの実行を理解する必要がある場合、並列結果を取得するにはどうすればよいでしょうか?チャンネルの使用にご協力いただく必要があります。
チャネル
チャネルとは、Go言語が言語レベルで提供するゴルーチン間の通信方法です。チャネルを使用して、2 つ以上のゴルーチン間でメッセージを渡すことができます。
チャネルはプロセス内通信メソッドであるため、チャネルを介してオブジェクトを渡すプロセスは、関数呼び出し時のパラメータ受け渡しの動作と一貫しています。たとえば、ポインタを渡すこともできます。クロスプロセス通信が必要な場合は、Socket や HTTP などの通信プロトコルを使用するなど、分散システムの方法を使用して解決することをお勧めします。 Go 言語はネットワークを非常に完全にサポートしています。
チャネルは型に依存します。つまり、チャネルは 1 つの型の値のみを渡すことができ、チャネルを宣言するときにこの型を指定する必要があります。 Unix パイプについてある程度の知識があれば、チャネルは簡単に理解でき、タイプセーフなパイプと考えることができます。
チャネルを定義するときは、チャネルに送信される値のタイプも定義する必要があります。チャネルを作成するには make を使用する必要があることに注意してください。コードは次のとおりです。
ci := make(chan int)
cs := make(chan string)
cf := make(chan interface{})
Windows や Linux が登場する前の昔に遡ると、プログラム開発時に同時実行性の概念はありませんでした。命令型プログラミング言語はシリアルに基づいており、プログラムは各命令を順番に実行し、プログラム全体の実行コンテキストは 1 つだけであるため、つまり、コールスタックとヒープです。
同時実行性とは、プログラムが実行時に複数の呼び出しスタックに対応する複数の実行コンテキストを持つことを意味します。各プロセスには、実行中に独自のコール スタックとヒープがあり、完全なコンテキストがあることがわかっています。オペレーティング システムがプロセスをスケジュールすると、スケジュールされたプロセスのコンテキストが保存されます。プロセスがタイム スライスを取得した後、プロセスのコンテキストをシステムに復元します。
オペレーティング システム全体の観点から見ると、複数のプロセスを並行して行うことができます。では、並行性の価値は何でしょうか?まず、次のシナリオを見てみましょう。
1) 一方で、応答性の高いグラフィカル ユーザー インターフェイスが必要ですが、他方では、プログラムは多数の操作や IO 集中型の操作を実行する必要があり、インターフェイスが応答して操作を実行できるようにする必要があります。同じ時間です。
2) 当社の Web サーバーが大量のユーザー要求に直面すると、ユーザーに個別に応答するためにより多くの「Web サーバー ワーク ユニット」が必要になります。
3) 私たちのトランザクションは分散環境にあります。同じワークユニットが異なるコンピュータ上で断片化されたデータを処理します。コンピュータの CPU はシングルコア (コア) からマルチコアに発展し、プログラムはすべてシリアルです。のコンピュータハードウェアは活用されていません。
4) IO 操作によりプログラムがブロックされ、プログラム全体が停止し、他の IO 関連タスクは実行できません。
上記の例からわかるように、シリアル プログラムは多くのシナリオで要件を満たすことができません。以下に、同時実行が不可欠であることを誰もが理解できるように、同時実行プログラムのいくつかの利点をまとめます。
- 同時実行により、問題モデルをより客観的に表すことができます。
- 同時実行により、CPU コアの利点を最大限に活用してプログラムの実行効率を向上させることができます。
- 同時実行では、CPU やその他のハードウェア デバイスの固有の非同期性を最大限に活用できます。