初夏の怪談話:同期処理を嫌い、相互排他を避けて非同期にしたら・・・

待っている地獄があります。それは・・・

 

 

マルチプロセス/マルチスレッドな環境では同期のために相互排他が必要となる場合が多いかと思います。たとえば

 

   

共通リソース(たとえばスレッド管理テーブル)を保護するためにミューテックスを設置する

 

というようなものですね。

 

相互排他の問題点については各種教科書を見ていただくのがよいのですが、もっとも厄介なのは、根本的にデッドロックの発生が防げないことです。

 

で、知ってる人は知っている©アンパンマン、

 

   

セマフォ/ミューテックスを1個だけ使えば

   

デッドロックは発生しないぜ

 

というジャイアントロックグローバルロックと呼ばれる手法もあるにはあります。(アカデミックになんと呼ぶのが正解なのか知りませんが。)

 

OSレス環境のご経験のある皆様なら、これは割り込み禁止(マスク)フラグと同じ意味と考えれば分かっていただけるかと思います。

 

 

 

さて、マルチコアの恩恵云々を無視して、シングルスレッド/シングルコンテキストで動作する仕組みなら、同期は不要になります。

 

これを具体化したものは、たとえば、GUIフレームワークでありがちなメッセージループや、自称未来の組み込みOSでありがちなシグナルベースシステムなどです。これらは同期呼び出しを非同期呼び出しに変換しているわけです。

 

で、やっぱり知ってる人は知っている©アンパンマン、

 

   

非同期システムキューあふれの問題があるぜよ

 

ということを知らない方が結構おらっしゃるようなのでここで指摘しておきます。

 

VxWorksなどでも「キューフル」と恐れられている現象です。

 

GUIフレームワークキューフルはマウスが効かない、システムリソースが枯渇するなどの現象で間接的に体験している方も多いかと思います。

 

◆◆◆

 

最近、ノンブロッキング処理について

 

   

同期処理を非同期化していい感じ

 

とノーテンキに解説しているのをみかけたもので、ひそやかに指摘しておきました。

 

(広義の)I/Oが遅い、あるいはCPUリソースが不足気味の環境では非同期システムの挙動は文字通り間抜けなものとなります。同期よりも非同期の方が、CPUリソースをより効率的に利用できる(かつデッドロックを避けられる)チャンスは高いわけですが、不足した場合の挙動は大して変わりません。

 

キューによって暗黙的に相互結合されたシステムでは、キューフルの発生箇所と原因箇所は遠く離れた場所になります。デバッグが困難になりがちです。キューごとに、待ち合わせコンテキストをダンプするデバッグ支援機能がないと話にならない場合がほとんどです。

 

 

 

また、キューをメモリの許す限り伸ばせばよいと意味不明な主張をされる方も時々おられます。どうせキューの最大値は見積もれないのだから、キューの長さを固定するのがキューフルの原因だとかなんとか。

 

キューの最大値を見積もれないのは、システムの挙動が分からないと自白しているのと同じで、単なる責任放棄なのです。

 

 

 

キューは日本語で待ち行列ですが、待ち行列理論については、ざまざまな解析手法があるわけで、(昨今はやりの)統計学的に、最大値を決めることも可能なはずです。

 

正しく設計していてかつ、それを越えてくるのはおそらく、バグが原因なのでしょう。

 

 

 

バグのないシステムは書けないわけですが、それを言い訳にして、設計できるキューの長さの見積もりをしないで責任放棄してよいわけではありません。