はじめに

この資料は、Delight 2025年春合宿「並行・分散プログラミングゼミ」の教材です。

並行・分散プログラミングゼミ

メンターkekeho
受講生yunative, vito

本ゼミでは、並行プログラミングおよび分散プログラミングの基礎を学びます。

現代のプログラマは、複数の処理を同時に動かすプログラムを書く必要があります。 現代のコンピューターには複数のCPUコアが搭載されています。プログラマはそれらをフル活用して、圧倒的パフォーマンスを発揮するソフトウェアを書く必要に迫られています。 また、大規模なクラウド環境では、複数台のコンピュータを組み合わせて大きな問題を解いたり、データを分散配置して障害耐性をつけたり、より低レイテンシでデータを提供したりする必要があります。

こうした環境下では、「並行性モンスター」があなたの前に立ちはだかります。 複数のCPUやマシンで同時にプログラムを動かすということは、次のような問題を生みます。

  • 競合状態 (Race Condition)
    複数のスレッド・プロセスが共有メモリに非同期でアクセスした場合、その実行順序により結果が変わります。実行順序をプログラマが予測することは困難です。

  • デッドロック、ライブロック、飢餓状態 (Deadlock, Livelock, Starvation)
    複数のスレッド・プロセスが、お互いの処理を待ち続け、なかなか自分の処理を進めることができずに、処理が完了しないということが起こります。

また、特に分散プログラミングでは、次のような問題が発生します。

  • 一貫性 (Consistency) の欠如
    分散システムでは、各プロセスは別々のマシンで実行されており、メモリの状態やデータが分散しています。 しかしユーザーに対してあたかも1つの大きなシステムのように見せるためには、どのプロセスも一貫した応答を生成する必要があります。 一部のデータが古かったり、あべこべな状態になっていてはいけません。

  • 耐障害性 (Fault tolerance)
    分散システムは、しばしば耐障害性を高めるために構築されます。 1台のノードが故障しても全体として通常通り稼働し続けることを保証するコードを書くことは、非常に困難であり、アルゴリズムへの深い理解が必要とされます。

本ゼミでは、上記の「並行性モンスター」と上手に付き合い、圧倒的パフォーマンス・耐障害性を発揮するプログラムを書くために、必要な基礎知識を実装を通じて学びます。 本ゼミを終えることで、最新の超絶技巧アルゴリズムなどを学ぶフェーズに入ることができるでしょう。 ソフトウェアのちからで、より安心安全かつ生産性の高い社会を実現し、世界を変えましょう。

おことわり

時間がなかったので、問題集(以下の何か)になりました。ごめんなさい。 その場でたくさん教えます。あとはC言語クイックリファレンスを持ってきたので、見ながら進めてください。

ルール

書籍・インターネット等で自由に調べてください。 AIは、調べ物目的であれば使用してかまいません。 ただし、書いたコードをメンターがレビューするので、答えられるようにしておいてください。

並行プログラミング

スレッド

問1-1: スレッドの作成

スレッドを2つ作成し、それぞれのスレッドから以下の出力をするプログラムを書きなさい。

$ ./thread_1
Hello, World! from thread #1
Hello, World! from thread #2

#1と#2の順番は異なってOK。

問1-2: 共有メモリにアクセス

変数int xを用意して、0で初期化しなさい。

その後、変数xを書き換えるwriterスレッドと、それを読み取るreaderスレッドを作成しなさい。 writerスレッドは、2秒間隔で値の書き換えを行いなさい。 readerスレッドはwhileループで変数を読み取り、変更を検知したらその値を出力しなさい。

以下の出力を生成しなさい。

$ ./thread_2
#Reader: Read x = 0
#Writer: Set x = 10
#Reader: Read x = 10
#Writer: Set x = 20
#Reader: Read x = 20

問1-3: 共有メモリにアクセス2

変数int countを用意を用意しなさい。 そしてスレッドを5つ作り、10000回のforループで1づつ加算しなさい。 最後に、メインスレッドが合計結果を出力しなさい。 結果は50000になるかな?

(コンパイルするときに、最適化レベルを0にしてください。)

$ ./thread_3
Sum: ???

問1-4: 排他制御

問1-3を改良し、排他制御をして、合計値が50000になるようにしてください。

$ ./thread_4
Sum: 50000

プロセス

問1-5: プロセスの作成

forkシステムコールでプロセスを2つ作成し、それぞれのプロセスから以下の出力をするプログラムを書きなさい。

$ ./process_1
Hello, World! from process #1
Hello, World! from process #2

#1と#2の順番は異なってOK。

問1-6 プロセス間のメッセージング

値を送るproducerプロセスと、値を読み取るconsumerプロセスを作成しなさい。 また、pipeシステムコールでパイプを作成し、値を送受信しなさい。

$ ./process_2
#Producer: Send Hello
#Consumer: Recv Hello
#Producer: Send World
#Consumer: Recv World

2. ネットワークプログラミング

問2-1, 2-2: UDPとTCPそれぞれで、2人で話せるチャットアプリを作ってみよう

3. 分散プログラミング

概要

CRDT Counter

頑張って作ってみて!

自由課題

なんかテーマ決めて、頑張って作ってみて!

おすすめ書籍・記事

並行プログラミング

  • The Art of Multiprocessor Programming

分散プログラミング

  • Distributed Systems
  • データ指向アプリケーションデザイン

ネットワークプログラミング