再入可能 (サイニュウカノウ) とは | 意味や読み方など丁寧でわかりやすい用語解説
再入可能 (サイニュウカノウ) の読み方
日本語表記
さいにゅうかのう (サイニュウカノウ)
英語表記
reentrant (リエントラント)
再入可能 (サイニュウカノウ) の意味や用語解説
再入可能とは、コンピュータプログラムにおける関数やサブルーチンが持つ性質の一つである。具体的には、ある関数が実行を完了する前に、複数のプロセスやスレッドから同時に、あるいは割り込み処理によって再度呼び出されたとしても、それぞれの処理が互いに干渉することなく、各々が期待された結果を正しく返すことができる性質を指す。この性質を持つコードは「リエントラントなコード」とも呼ばれる。現代のオペレーティングシステムや組み込みシステムのように、複数の処理が並行して実行される環境では、この再入可能性という概念がシステムの安定性と信頼性を確保する上で極めて重要となる。例えば、OSが提供するライブラリ関数は、様々なアプリケーションから同時に呼び出される可能性があるため、多くの場合、再入可能であることが求められる。 再入可能という性質がなぜ重要になるのかを理解するためには、並行処理の場面を想像するとよい。一つの例として、複数のプログラムが同時に同じファイルへログを書き込む処理を考える。このとき、ログを書き込むための関数が共有ライブラリとして提供されているとする。もしこの関数が再入可能でなければ、あるプログラムが書き込み処理を行っている最中に、別のプログラムが同じ関数を呼び出すと、内部で管理しているデータが混在し、ファイルの内容が破壊されたり、システムが不安定になったりする危険性がある。また、よりクリティカルな例として、割り込み処理が挙げられる。ある関数を実行している最中に、ハードウェアからの割り込みが発生し、その割り込みを処理するプログラム(割り込みハンドラ)が、偶然にも実行中だった関数と同一の関数を呼び出すケースがある。このとき、元の処理と割り込み処理とで、関数の内部状態が衝突してしまうと、予期せぬ動作を引き起こす。再入可能な関数は、このような状況でも各々の呼び出しが独立して扱われるため、安全に処理を継続することができる。 では、どのようにしてプログラムを再入可能にするのか。そのための重要な原則がいくつか存在する。第一に、関数が静的なデータやグローバル変数といった、複数の呼び出し間で共有されるメモリ領域を直接書き換えないことである。これらの変数はプログラムのどこからでもアクセス可能なため、ある処理が値を変更すると、同時に動作している他の処理に意図しない影響を与えてしまう。もし共有データへのアクセスが不可欠な場合は、そのデータを関数に引数として渡すか、呼び出し側でデータ領域を確保し、そのポインタを渡すといった設計にする。第二に、関数内で使用する変数は、スタック上に確保されるローカル変数(自動変数)に限定することである。ローカル変数は関数が呼び出されるたびにスタックメモリ上に新しく確保され、関数の実行が終了すると解放される。これにより、関数が複数回同時に呼び出されても、それぞれの呼び出しインスタンスは自身専用の独立した変数領域を持つことになり、データが混ざり合うことがない。第三に、自己書き換えコードを含まないことである。実行中に自分自身のプログラムコードを書き換えるような処理は、再入可能性を著しく損なう。最後に、内部で呼び出す他の関数もすべて再入可能でなければならない。どれか一つでも再入可能でない関数を呼び出してしまうと、その関数全体として再入可能性は保証されなくなる。 ここで、再入可能とよく似た概念に「スレッドセーフ」がある。これらは混同されやすいが、厳密には異なる意味を持つ。スレッドセーフとは、複数のスレッドから同時にアクセスされても問題が起きないように設計されていることを意味する。これは通常、ミューテックスやセマフォといった排他制御の仕組みを用いて、共有リソースへの同時アクセスを防止することで実現される。一方、再入可能は、そもそも共有リソースに依存しない、あるいは共有リソースを更新しないように設計することで、排他制御なしに安全性を確保する。したがって、再入可能な関数は本質的にスレッドセーフであると言える。しかし、スレッドセーフな関数が必ずしも再入可能であるとは限らない。例えば、グローバル変数をミューテックスでロックしてから更新する関数はスレッドセーフである。しかし、あるスレッドがこの関数を実行してロックを獲得した状態で割り込みが発生し、割り込みハンドラから再度同じ関数が呼び出された場合、割り込みハンドラは自分自身のスレッドが獲得済みのロックを待つことになり、デッドロックに陥ってしまう。このため、この関数はスレッドセーフではあるが、再入可能ではない。このように、再入可能性は、特に割り込みハンドラやシグナルハンドラといった、より厳しい制約のある環境で求められる、より強力な安全性の指標である。システムプログラミングの世界では、この違いを正確に理解し、目的に応じて適切な設計を選択する能力がエンジニアには求められる。