概要
- The Art of Multiprocessor Programming 第2版の書評と実用性への疑問
- futex (Fast Userspace Mutex)の重要性と従来のSystem Vロックとの違い
- futexの 仕組み・API設計 ・各OSでの実装例
- mutex /スピンロックの基礎・futexを使った実装例
- 書籍に不足する 実践的な内容 の補完
The Art of Multiprocessor Programming 第2版 書評とfutexの重要性
- Phil Eaton's book club で扱う書籍は業界評価が高く、2021年にアップデートされた最新版
- 著者も有名で、 並行プログラミング経験者 としても学びが多いと期待していた
- しかし、 futex に一切触れていない点に強い疑問
- futexは単なるmutexではなく、 現代の高性能な並行処理の基盤 となるプリミティブ
- System V時代の セマフォ中心のロック機構 はスケーラビリティに難あり
- Linuxが futex を導入(2002年)、以降Windows(2012年)、macOS(2016年)なども追随
- 現代のpthread等のシステムライブラリは futexベース の実装が主流
futexの基本と従来ロックとの違い
- futex は「fast user-space mutex」の略だが、mutexそのものではなく 並行プリミティブのビルディングブロック
- 従来(System V IPC)のロックは セマフォ でロックと待機が一体化していた
- futexは ロック操作と待機/起床操作を分離 し、柔軟性とパフォーマンス向上を実現
- 無駄なシステムコール回避 が容易になり、ユーザー空間で完結できる操作が増加
- 例えば、 unlock時に待機スレッドがなければカーネル呼び出し不要 (System Vでは必須)
futexのAPIと動作概要
- futex_wait() :指定した状態(値)でなければ即失敗、合致すればカーネル内の待機リストにスレッドを登録しブロック
- futex_wake() :指定したメモリアドレスの待機リストからスレッドを起こす。基本は1または全スレッドを起床
- WindowsのAPI名「 WaitOnAddress」は本質をよく表現
- 待機対象は32bit整数(もしくは64bit)。値の意味はOSは関知しない
- 待機時に 現在値を明示 することで、既に状態変化があった場合に無駄な待機を防止
futexの実装例(Linux/macOS)
- atomicな32bit整数型 をfutexとして利用
- Linux ではglibcにラッパーがないため、
syscallで直接呼び出しfutex_wait_timespec:状態一致時に待機、タイムアウトも指定可能futex_wake:1スレッドまたは全スレッドを起床
- macOS では
__ulock_wait2/__ulock_wakeを利用(新APIもあり)- ほぼ同様の機能を提供
mutex/スピンロックの基礎とfutex実装例
-
書籍は「mutual exclusion」の概念やスピンロックに多く紙面を割く
-
スピンロック は以下のようにatomic操作で簡単に実装可能
#include <stdatomic.h> #include <stdint.h> typedef _Atomic uint32_t h4x0r_spin_lock_t; static inline void h4x0r_spin_lock_init(h4x0r_spin_lock_t *lock) { atomic_store(lock, 0); } static inline void h4x0r_spin_lock_acquire(h4x0r_spin_lock_t *lock) { while (atomic_fetch_or(lock, 1)) ; } static inline void h4x0r_spin_lock_release(h4x0r_spin_lock_t *lock) { atomic_store(lock, 0); } -
futexベースのmutex を自作することで、無駄なCPU消費やシステムコールを減らせる
書籍に欠けている実践的内容
- futex のような現代的プリミティブの解説不足
- 実装例やAPIの使い方 に踏み込んだ説明がほぼ皆無
- 基礎理論と現実世界のギャップ を埋める知識の重要性
- 理論だけでなく、 OS・ハードウェア・コンパイラの最適化や落とし穴 にも注意が必要
まとめ
- The Art of Multiprocessor Programming は理論面で優れているが、 現代的な並行プログラミングの実践 には不十分
- futex のような重要プリミティブの理解と活用が不可欠
- 実装例を通じた学習 が、より現実的な並行処理設計の力につながる