ここまでの説明で、非同期プログラミングをすることで並列または並行で実行できるコードを記述できることが分かったと思います。(分からなかったら、僕の説明が悪かったです。スミマセン orz)

今、「並列または並行」と言いましたが、並列性と並行性は何が異なるのでしょうか?この2つの用語はときどき意味を区別されずに使われています。並列性と並行性はどのように異なるのかをこれから話していきます。

並行性と並列性の違い

「Go 言語による並行処理」という本にこのような 1 文が出てきます。

並行性はコードの性質を指し、並列性は動作しているプログラムの性質を指します。

この 1 文はかなり分かりやすく、興味深い表現です。次のコードを実行するとします。このとき、async_main関数で2つの非同期関数hogefugaを「並列」に動作するように書いています。


#![allow(unused_variables)]
fn main() {
async fn hoge() { // do something  }
async fn fuga() { // do something  }

async fn async_main() {
    let f1 = hoge();
    let f2 = fuga();

    // hoge,fugaの完了を待つ
    futures::join!(f1, f2);
}
}

では、このコード(async_main関数)を実行したとき、hogefugaという2つの関数は並列に動作するという「保証」はあるのでしょうか?

マシンの CPU が1コアだったら何が起きるのでしょうか?並列に動作しますか?この時hogefugaは並列に動作しているように見えますが、実際は 2 つの処理を素早く切り替えながら逐次実行しています。つまり、hogefugaは並行に動作します。このコードを 2 コアのマシン上で実行するとhogefugaは実際に並列に動作するでしょう。つまり、私達は「並列に走って欲しい並行なコード」を書いていますが、実際のところはプログラムのランタイムが様々な抽象化を行い「並列に動作させてくれる可能性がある」ということです。(様々な抽象化とは、OS 自体の違い,OS が動作しているプラットフォームの違い、CPU の違いなどが当てはまります。)

もう一度良いまずが、並列性は動作しているプログラム(非同期ランタイム)の性質であって、コードの性質ではないのです。