具体例
実世界の例をいくつか追加し、それらをソフトウェアエンジニアリングの世界に結び付けたいと思います。最初に、「同期」の直感的な定義と一致することを願っています:状況によっては、ホタルの点滅。次に、4x100の女子オリンピックリレーレースを検討します。第三に、軍事映画からの古い縄張りを考えてみましょう。
では、何が起こっているのか考えてみましょう。これらすべてがプロセスまたは時間的に拡張されたエンティティであることを観察することから始めましょう。ボウルが「同期」であり、ロックが「非同期」であると言うのは意味がありません。第二に、タンゴには2つかかります。「ランナーは同期している」とは言えません。何と同期しますか?最後に、2つのプロセスが同時に何かを行うためには、それらがすでにまったく同じ周波数と位相を持っている場合を除き、一方または両方が待機する必要があります。
分析
辞書の定義で、同期する2つのエンティティが「同時に発生または存在する」と書かれている場合、ホタルの光の概念と非常にうまく調和しています。残念ながら、ライトが「同期している」と言うことは、ホタルの照明プロセスが同期していることを言うのがずさんな方法です。
では、Apple SmartWatchとNTPを備えていないホタルの群れが、どうやって後端を同時にフラッシュできるのでしょうか。一貫性のあるテンポを設定する手段があり、それを少し調整することができれば、非常に簡単です。彼らはただ点滅し、彼らのすぐ後にもっと多くの人々が点滅すると、彼らは遅くなります(遅延を増加させます)。そのため、単純なフィードバックプロセスを使用して、本質的に同じテンポとフェーズに到達できます。ここで重要な所見は、それらが適切な瞬間が点滅するのを待つことによって同期を達成することに注意することです。
4x100レースは、両方の形式のプロセスタイミングが動作しているので興味深いものです。チーム内のランナーは同期され、異なるチームのランナーは「非同期」です。リレーの2人目のランナーは、最初のランナーが転送ゾーンに入るまで待たなければなりません。ハンドオフは、これら2人のランナー間の同期イベントです。ただし、異なるレーンのランナーは、別のレーンで何が起こっているかを気にしません。そして、確実にスローダウンしてハンドオフを同期しないでください。ランナーの各レーンは、互いに非同期です。繰り返しますが、同期には待機が必要ですが、非同期には必要ありません。
最後に、会社の兵士(小隊、消防隊など)は、敵を同時に攻撃できるように時計を同期する必要があります。一部の兵士は他の兵士より先に自分の位置に到着するか、敵により早く攻撃する機会があるかもしれません。しかし、驚きの要素があるため、同時攻撃は一般的に無計画な攻撃よりも効果的です。そのため、同期を達成するために、兵士の多くは行動するために指定された時間を待たなければなりません。
機能の定義
なぜこれを待つことに重点を置いているのですか?それは、待機が同期プロセスと非同期プロセスを区別する定義機能であるためです。知らない2つのプロセスがある場合、デフォルトでは、それらが非同期であると想定する必要があります。たとえば、荷物の配達と救急車の運転はほとんど同期されていません。2つのプロセスが実際に同期されていることを実証するには、非常に特別な瞬間、つまり同期ポイントを見つける必要があります。
荷物を降ろす配達ドライバーと病院に急行する救急車は、通常、「同期ポイント」として特定した時点を共有しません。一方、一斉に点滅するホタルは、点滅するたびに同期点を持ち、リレーランナーはバトンを渡すたびに同期点を持ち、兵士は攻撃を開始するときに同期点を持ちます。1つ以上の同期点を識別できる場合、プロセスは同期化されています。「syn-」は「with」または「together」を意味するギリシャ語のプレフィックスであり、「chrono」は「time」のギリシャ語のルートであるため、これは理解しやすいはずです。「同期」とは、文字通り「同時に」を意味します。
境界線
「同期」は、いずれかまたは両方のプロセスのライフタイム全体に必ずしも適用されるわけではないことに注意してください。私は「同期ポイントまでの待ち時間」にのみ適用されると主張します。したがって、2つのプロセスは、通信が必要な状態に達するまで非同期に動作し、同期され、情報を交換し、その後非同期で続行します。簡単な例は、コーヒーのために誰かに会うことです。明らかに、会議は同期ポイント(またはむしろ多く)であり、2人がそのポイントに到着するという事実は同期を示しています。しかし、私たちは二人がコーヒーのために会ったので、それらの二人の生涯とは言いません「同期」されています。それは彼らが出会った彼らの人生で唯一の瞬間だったかもしれません、そして彼らがする他のすべてはそれ以外は独立しています。
また、偶発的な会合が同期を示すということでもありません。2人の見知らぬ人が通りを通り過ぎた場合、ある時点で特定の場所にいるという事実は同期性を証明しません。また、バスを待っているベンチに一人が座っていて、別の人がたまたま通りかかっているという事実もありません。プロセスは、目的に合った場合にのみ同期します。
ソフトウェア接続
次に、ソフトウェアの非常に基本的なタスク、つまりファイルからの読み取りについて考えてみましょう。おそらくご存知のように、大容量記憶装置は通常、キャッシュまたはメインメモリよりも数千から数百倍遅いです。このため、オペレーティングシステムとプログラミング言語ライブラリは通常、同期および非同期の両方のI / O操作を提供します。ここで、プログラムに単一のスレッドしかない場合でも、この議論の目的上、OSは「別個のプロセス」であると考える必要があります。
同期する
「同期I / O読み取り」を行う場合、スレッドはデータが利用可能になるまで待機する必要があり、その時点でスレッドは継続します。これは、リレーランナーがバトンを次のランナーに渡すのとよく似ていますが、代わりに2人のランナーだけがトラックを一周し、2番目のランナーも最初に戻るリレーを想像してください。
この場合、プログラムスレッドとOS I / Oプロセスは「同時に発生(動作)」していないため、これらのプロセスが「同期」していると言うのは奇妙に思えます。しかし、それはそれを見る間違った方法です!「リレーチームのランナーは同時に走っていないので、同期されていません」と言っているようなものです。実際、両方のステートメントが間違っています!リレーチームのランナーが行うとしなければならないだけに非常に特定の瞬間に、同時に実行:手をオフバトンを。実際、リレーチームが最初から同期されていることを確信させるのは、レース中のこの特別な瞬間だけです!I / O要求と応答を「バトン」と見なすと、
一方、スーパーコンピューターでの有限要素解析などを考えると、大規模なグローバル状態を更新するには数千のプロセスがロックステップで動作する必要があることがわかります。一部のノードが他のノードより先に特定のタイムステップで作業を完了した場合でも、結果は空間を介して近隣に伝播するため、すべてのノードがタイムステップの完了を待つ必要があります。この種の同期はホタルのようなものです。すべてのアクターは同じ種類のタスクを実行しています。
プロセスの多様性
このため、「同種の同期」、「異種の同期」、および「順次の同期」という3種類のことが起こっていることを確認するのに役立つ用語をいくつか作成できます。したがって、アクターが同じタスク(FEA、ホタル)を同時に実行している場合、アクターは「均質」です。異なるタスクを同時に実行している場合(実行中の兵士対目的地へのクロール対水泳、ゲーム内の物理対音声、AIスレッド)、それらは「異種」です。一度に1つずつタスクを実行している場合、それらは「シーケンシャル」(リレーランナー、I / Oのブロック)です。外見は非常に異なりますが、1つの重要な特性を共有しています。すべてのタイプのアクターは、全員が同時に同期ポイントに到着することを保証するためにいくつかの待機を実行します。 同期ポイント間、または「同じアクションを実行する」ことは、同期性の特性とは無関係です。
GPUのレンダーパイプラインは、すべてがフレームを一緒に終了し、一緒に新しいフレームを開始する必要があるため、同期的です。彼らは同じ種類の仕事をしていて、すべて一緒に活動しているので、彼らは同質です。しかし、サーバーのメインゲームループと、リモート入力を処理するブロッキングI / Oスレッドは、非常に異なる種類の作業を行うため異種です。接続が使用されます。それでも、アトミックに状態を共有する必要があるため、それらは同期されます(プレーヤーは部分的なゲームワールドの更新を見たり、サーバーがプレーヤー入力の断片だけを見たりしてはなりません)。
非同期
ここで、「非同期I / O読み取り」を考えてみましょう。プログラムがストレージにデータのビットを読み込む要求をOSに送信すると、呼び出しはすぐに戻ります。コールバックを無視して、ポーリングに集中しましょう。一般に、プログラムがデータを利用できる瞬間は、プログラムのスレッドに関する限り、特別な時点には対応していません。プログラムがデータを明示的に待機していない場合、スレッドはその瞬間がいつ発生したかを正確に知りません。次回のチェック時にデータが待機していることを検出するだけです。
OSとプログラムスレッドがデータの引き渡しに同意する特別な会議時間はありません。彼らは夜に通過する2隻の船のようです。非同期性は、この待機の欠如によって特徴付けられます。もちろん、プログラムスレッドは結局、I / O操作を待つことになることがよくありますが、そうする必要はありません。I / Oフェッチの実行中に他の計算を喜んで実行し、後で余裕があるときにのみチェックできます。もちろん、OSがデータのフェッチを完了すると、待機することもありません。データをどこか便利な場所に置き、そのビジネスについて続けます。この場合、プログラムはバトンをOSに渡し、OSは後で出てきて、データと共にバトンを地面に落とし、トラックから歩き去ります。プログラムは、ハンドオフの受信を待機している場合と待機していない場合があります。
平行度
ソフトウェアで関数を「非同期」としてマークすると、多くの場合、並列処理が必要になります。ただし、並列処理は同期を意味するものではないことに注意してください。ホタルは、同期と非同期の両方の動作を示したため、良い例です。ハエの大部分は一斉に点滅しましたが、多くのハエは明らかにグループの残りの部分と同調しておらず、よりランダムに点滅していました。ハエは同時に行動していたかもしれませんが、それらはすべて同期していませんでした。
あるコードを「非同期」としてマークすると、おかしなように見えます。これは、そのようにマークされていない残りのコードが「同期」であることを意味するためです。それは一体何の意味ですか?「同期」にはタンゴに2つ必要だと主張しませんでしたか?しかし、単一のスレッドで実行されるコードについて話している場合はどうでしょうか?この場合、一歩下がって、プログラムを状態のシーケンスおよびそれらの状態間の遷移として考える必要があります。プログラム内のステートメントは、状態遷移を引き起こします。ステートメントで開始および停止する「マイクロプロセス」と考えることができます。言語によって定義されたシーケンスポイントは、実際、これらの「マイクロプロセス」の同期ポイントです。したがって、シングルスレッドを表示できます。
プログラミング言語の整合性により、ステートの更新がステートメント間で干渉しないことが保証され、シーケンスポイントは、コンパイラが観察可能な最適化を行うことを許可されない境界を定義します。たとえば、ステートメント内の式の評価の順序は未定義または指定不足である場合があり、コンパイラーはさまざまな方法でステートメントを最適化できます。しかし、次のステートメントが始まるまでに、PL自体が正常であれば、プログラムは明確に定義された状態になっているはずです。
今では、「非同期」の意味が明確になっているはずです。これは、コードブロック内の暗黙の同期コントラクトが非同期ブロックに対して免除されることを正確に意味します。通常、順次(一貫性のある、同期の)計算モデルによって暗示される安全性の保証なしに、プログラムの状態を個別に更新することができます。もちろん、これは、一貫性のない状態でプログラムの状態を破壊しないように特別な注意を払う必要があることを意味します。これは通常、非同期ブロックと調整するために、限定された明示的な同期を導入することを意味します。これは、非同期ブロックが異なる時点で非同期と同期の両方になり得ることを意味することに注意してください!しかし、同期は単に同期点の存在を示しているにすぎないことを思い出してください。この概念を受け入れるのに問題はないはずです。