コース一覧
OS入門:プロセス・メモリ・ファイルシステム
Mutex と Semaphore

OS入門:プロセス・メモリ・ファイルシステム

OSがCPU・メモリ・ストレージをどのように管理しているかを、プロセス、スレッド、仮想メモリ、ファイルシステム、同期と並行性から体系的に学びます。アプリケーションの裏側で何が起きているかを説明できるようになります。

1
OS とは
0. コンピューターとOSの役割15分
1. OSの歴史(バッチ→マルチタスク→マルチユーザー)15分
2. カーネルとユーザーランド15分
3. システムコールの仕組み15分
4. Linux / macOS / Windows のアーキ比較15分
2
プロセスとスレッド
0. プロセスとは15分
1. スレッドとプロセスの違い15分
2. コンテキストスイッチ15分
3. スケジューラとアルゴリズム15分
4. プロセス間通信(IPC)15分
3
メモリ管理
0. メモリ階層(レジスタ→キャッシュ→RAM→ディスク)15分
1. 仮想メモリ15分
2. ページングとスワップ15分
3. mmap とメモリマップトファイル15分
4. ガベージコレクション概要15分
4
ファイルシステム
0. ファイルシステムとは15分
1. i-node とディレクトリ15分
2. ext4 / APFS / NTFS の違い15分
3. ジャーナリングと耐障害性15分
4. パーミッションと所有者15分
5
同期と並行性
0. レースコンディション15分
1. Mutex と Semaphore15分
2. デッドロック15分
3. 非同期と並行15分
4. イベントループと epoll15分

OS入門:プロセス・メモリ・ファイルシステム

01コンピューターとOSの役割
02OSの歴史(バッチ→マルチタスク→マルチユーザー)
03カーネルとユーザーランド
04システムコールの仕組み
05Linux / macOS / Windows のアーキ比較
06プロセスとは
07スレッドとプロセスの違い
08コンテキストスイッチ
09スケジューラとアルゴリズム
10プロセス間通信(IPC)
11メモリ階層(レジスタ→キャッシュ→RAM→ディスク)
12仮想メモリ
13ページングとスワップ
14mmap とメモリマップトファイル
15ガベージコレクション概要
16ファイルシステムとは
17i-node とディレクトリ
18ext4 / APFS / NTFS の違い
19ジャーナリングと耐障害性
20パーミッションと所有者
21レースコンディション
22Mutex と Semaphore
23デッドロック
24非同期と並行
25イベントループと epoll

OS入門:プロセス・メモリ・ファイルシステム

Mutex と Semaphore

区間そのものに鍵をかける

前回の引き落としは、読んでから書き戻すまでを 2 人に同時に通したせいで壊れました。ならば、その区間に入る前に鍵を取り、出るときに返す約束にします。鍵は 1 つしか無いので、2 人目は 1 人目が返すまでその場で待たされます。この鍵が ミューテックス です。

Python

import threading

lock = threading.Lock()

def withdraw(account, amount):
    with lock:
        if account.balance >= amount:
            account.balance -= amount
            account.history.append(amount)

with lock: に入るところで鍵を取り、ブロックを抜けるところで返します。残高の確認から履歴の追加までが 1 人分ずつ順に実行されるので、前回の表のような割り込まれ方はしなくなります。

acquire() と release() を自分で書くこともできますが、途中で例外が飛ぶと release() を通らず、鍵を持ったまま誰も帰ってこない状態になります。言語が用意している構文を使うのが鉄則です。Python の with、Java の synchronized、Go の defer mu.Unlock()、Rust のガードは、どれも「必ず返す」ことを保証するための形です。

鍵の持ち主が決まっている

ミューテックスの特徴は、取ったスレッドだけが返せることです。これは制限ではなく安全装置で、「関係ないスレッドが勝手に鍵を返してしまい、区間に 2 人入る」という事故を仕組みとして防いでいます。

鍵が 1 つだと、全員が 1 列に並ぶ

上の例には無駄があります。鍵はプログラム全体で 1 つなので、まったく別の口座への引き落としまで順番待ちになります。口座が 1 万あっても、同時に動けるのは 1 人だけです。

そこで鍵を口座ごとに持たせます。別々の口座なら並行に進み、同じ口座に来たときだけ待ちが発生します。この「鍵をどの単位で持つか」を粒度と呼び、並行時の性能をほぼ決めてしまいます。粗くすれば安全だが遅く、細かくすれば速いが、扱う鍵の数が増えるぶん事故の余地も増えます。

1 人ではなく、N 人まで通したいとき

守るのではなく、数を絞りたい場面もあります。外部 API へ 500 件のリクエストを投げたいが、同時接続は 5 本までに抑えたい、といった要求です。

このときは、内部にカウンタを持つ セマフォ を使います。入るときにカウンタを 1 減らし、0 になったら次の人は待ち、出るときに 1 戻します。

Python

sem = threading.Semaphore(5)

def fetch(url):
    with sem:
        return http_get(url)

ミューテックスは「同時に 1 人」、セマフォは「同時に N 人」です。上限 1 のセマフォはほぼミューテックスとして働きますが、セマフォには持ち主の概念が無く、入ったのとは別のスレッドが返せます。壊れないように守りたいのか、数を絞りたいのかで選び分けます。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • ロック「他の人触らないでね」と DB に予約する
  • スレッド1 つの質問に紐づく返信の集まり
  • エンドポイント「この URL を叩くとこの機能が動く」入口の住所
  • APIアプリ間でデータをやり取りする窓口
  • リクエストWeb 通信の基本単位、ブラウザの問い合わせとサーバーの返答
  • カウンタ数を保持して増減する典型 UI
生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/27·更新 2026/08/26

関連レッスン

  • デッドロック

    複数スレッドが互いのロックを待ち合って永久停止するデッドロックの成立条件と、ロック順序の固定やタイムアウトなど複数の防止策を実務目線で解説します。

  • 非同期と並行

    並行と並列の違い、I/O 待ちの間に他の仕事を進める非同期処理の考え方を、コールバックから async/await への進化とあわせて初学者にも分かる形で解説します。

  • イベントループと epoll

    I/O 完了イベントを一スレッドで順次処理するイベントループと、その基盤となる epoll や kqueue を使って大量同時接続をさばく仕組みを解説します。

分からないところは Tap (AI先生) に質問できます

24 時間いつでも、あなたのレベルに合わせて日本語で答えます。