ミューテックス

複数のスレッドが共有リソースに同時アクセスすることを防ぐ排他制御の同期プリミティブ

並行処理非同期

ミューテックスとは

ミューテックス (Mutex: Mutual Exclusion) は、複数のスレッドが共有リソースへ同時にアクセスすることを防ぐ同期プリミティブである。1 つのスレッドがロックを取得している間、他のスレッドは解放されるまで待機する。

ミューテックス vs セマフォ

観点 ミューテックス セマフォ
同時アクセス数 1 (排他) N (カウンタ)
所有権 ロックした者だけが解放 誰でも解放可能
用途 共有リソースの保護 リソースプールの制限

Rust の Mutex

use std::sync::{Arc, Mutex};
use std::thread;

let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];

for _ in 0..10 {
    let counter = Arc::clone(&counter);
    handles.push(thread::spawn(move || {
        let mut num = counter.lock().unwrap();
        *num += 1;
    })); // ロックはスコープを抜けると自動解放
}
for h in handles { h.join().unwrap(); }
assert_eq!(*counter.lock().unwrap(), 10);

Go の sync.Mutex

var mu sync.Mutex
var count int

mu.Lock()
count++
mu.Unlock()

デッドロック

スレッド A: Lock(X) → Lock(Y) を待つ
スレッド B: Lock(Y) → Lock(X) を待つ
→ 互いに相手の解放を待ち、永久に停止
対策 説明
ロック順序の統一 常に X → Y の順でロック
タイムアウト 一定時間で諦める
ロックの粒度を細かく 必要最小限の範囲でロック

Lambda とミューテックス

Lambda はリクエストごとに独立した実行環境で動作するため、プロセス内のミューテックスは不要。複数の Lambda 間の排他制御には分散ロック (DynamoDB の条件付き書き込み) を使う。

// Lambda: 分散ロック (ミューテックスの代替)
await db.put({
  TableName: 'locks',
  Item: { lockId: 'resource-1', owner: requestId, expiresAt: Date.now() + 30000 },
  ConditionExpression: 'attribute_not_exists(lockId) OR expiresAt < :now',
  ExpressionAttributeValues: { ':now': Date.now() },
});

ロックフリーアルゴリズム

方式 説明
CAS (Compare-And-Swap) CPU 命令でアトミックに更新
Atomic 型 ロックなしでカウンタを更新
不変データ データを変更しない設計

ミューテックスを扱う関連書籍も多い。

関連用語