yohhoyの日記

技術的メモをしていきたい日記

(翻訳)Boost.Threadライブラリが"イベント変数"を提供しない理由

元文書:Boost.Thread 1.34.1 Rationale for not providing Event Variables, Beman Dawes氏

訳出メモ:

  • 元文書はBoost 1.35.0以降で削除されてしまったが*1、基本的なAPI設計は変わっておらずBoost 1.49.0現在でも通用する内容となっている。
  • 訳文中では "Event Variables" を直訳して "イベント変数" としている。同期プリミティブとしての "イベント変数" という用法はあまり一般的ではないが、機能的にはWindows APIのイベントオブジェクト(Event Objects)やPOSIXWindows APIセマフォsemaphoresSemaphore Objects)が相当する。
  • 2021-11-17追記:C++20標準ライブラリでは<semaphore>ヘッダでセマフォが提供される。

イベント変数を提供しない理論的根拠

イベント変数(Event Variables)は、あまりに使い方を間違えやすいものです。代替手段として、より安全なboost::condition(訳注:Boost 1.35.0以降はboost::condition_variable)変数が存在します。[グラフィカルユーザインタフェース(GUI)イベントとは別の概念であることに注意。後者についてはここでは議論しません。]

イベント変数は初期の同期プリミティブの一つでした。ネイティブWindowsマルチスレッディングAPIなどでは、今でも利用されて続けています。しかし、優秀なコンピュータサイエンス研究者やマルチスレッドシステムのベテラン開発者達は、イベント変数は本質的に間違いを起こしやすいために決して使われないべきであり、またマルチスレッディングライブラリに含めるべきでないと確信しています。

Per Brinch Hansen*2はイベント変数について詳細に分析し、「イベント操作はプログラマに送受信プロセス間の相対速度に注意を払うことを強制する」と指摘しています。彼の要約は:

前述タイプのイベント変数は、システムデザインにとって実用的でないと結論せざるを得ない。2つのプロセス間相互作用の結果は、プロセスの実行速度から独立しているべきである。

今日でもWindowsプラットフォームを使う熟練プログラマは、細心の注意を払ってイベント変数を利用した過去の苦い経験をしてもなお、イベント変数は依然としてエラーの温床であると報告しています。あからさまな問題はイベント変数とミューテクス(mutex)の組み合わせなどで回避できますが、競合状態(race condition)からリソースの過剰使用といった別の問題へ形を変えただけです。体験談のうち最も悲惨な側面の一つは、多くの不具合が潜在化されるというものです。一見して正しく動作しているプログラムも、環境要因や利用パターンの変更などでスレッド動作タイミングが変化すると、隠れたタイミング依存性のせいで異常動作を引き起こします。

Boost.Threadからイベント変数を除外するという決定は、一部のWindowsプログラマを驚かせています。彼らはイベント変数を使ったプログラムを書いていますし、どこに問題があるのかと不思議がります。この状況は30年前の “gotoは有害だと考えらえれる” ("goto considered harmful") 論争に似ている気がします。goto同様、イベント変数も正しく動かない訳ではありません。しかしながら、ほぼ全てのプログラマにとって、代替品の方がコードの読み書き、デバッグ、メンテナンスが容易ですし、潜在的な不具合を作りだし難いことでしょう。

*1:Boost.Threadライブラリメンテナが変わったため?(William E. Kempf氏→Anthony Williams氏)

*2:ACM Computing Surveys. Vol. 5. No. 4. December, 1973. Per Brinch. "Concurrent Programming Concepts".