リエントラント
出典: フリー百科事典『ウィキペディア(Wikipedia)』
リエントラント(Reentrant、再入可能)とは、プログラムやサブルーチンが、静的な内部状態をもたないので、再帰的にも、複数のスレッドからも、データを壊すおそれなく呼び出せる場合をいう。関数がリエントラントであるためには、静的データを保持してはならず、静的データへのポインタを返してもいけない。呼出し側が提供したデータだけに基づいて処理を行わなければならず、リエントラントでない関数を呼び出してはならない。
リエントラントなコードはスレッドセーフであるほか、データを壊すことなく処理を一時中断することもできる。
セマフォのような同期機構を用いて静的データへのアクセスを保護したコードは、スレッドセーフではあるがリエントラントではない。
スレッドセーフなコードを書く場合に、その手法として、リエントラントなコードを採用することがある。しかし、リエントラントなコードは、同期機構を用いた単にスレッドセーフなコードを書くのに比べて難度が高い。
誤解されることが多いが、仮想記憶によって物理記憶上のプログラムのイメージを複数のプロセスのアドレス空間にマッピングして使用するなどの設計と、リエントラントという概念は厳密には同じではない。
[編集] 例
以下のコードにある関数 f
も g
もリエントラントではない。
int g_var = 1;
int f()
{
g_var = g_var + 2;
return g_var;
}
int g()
{
return f() + 2;
}
上記のコードで、f
はグローバル変数 g_var に依存している。したがって、2つのプロセス(スレッド)が f
を実行すると、g_var に同時並行的にアクセスし、結果はタイミングに依存することになる。したがって、f
はリエントラントではない。その f
を呼び出している g
もリエントラントではない。
これらを若干変更したリエントラントである版を以下に示す:
int f(int i)
{
return i + 2;
}
int g(int i)
{
return f(i) + 2;
}
新しい版では、グローバル変数 g_var は使われていない。引数を渡して、それに基づいて処理を行って結果を返す。共有される可能性のあるオブジェクトにはアクセスしないようになっている。その代わり、呼出し側が前回の戻り値を引数として渡してやらなければならない。このように、リエントラントなサブルーチンでは、必要な静的データは呼出し側が管理しなければならない。
[編集] 関連項目
[編集] 外部リンク
いずれも英文
- Article "Use reentrant functions for safer signal handling" by Dipak K. Jha
- Writing Reentrant and Thread-Safe Code
カテゴリ: プログラミング | ソフトウェアパターン | 並行計算