1. 導入:なぜSTATIC変数は危険なのか
メインフレームのオンライン環境(CICSやIMSなど)では、限られたリソースを効率的に使うため、一つのプログラムを複数のトランザクションで共有して実行する「再入可能(リエントラント)」な設計が求められます。しかし、PL/IやC言語で何気なく使用する「STATIC変数」は、この再入可能性を破壊する最大の要因です。意図しない値の上書きを防ぎ、バグのない安定したシステムを構築するために、STATIC変数の正しい扱い方を理解しましょう。
2. 基礎知識:STATIC変数と再入可能性
STATIC変数とは、プログラムの実行開始から終了まで、メモリ上の固定された領域に保持され続ける変数のことです。
対して、再入可能性(Reentrancy)とは、あるプログラムが実行されている途中で別の処理から呼び出されても、前の処理のデータを壊すことなく正しく動作できる性質を指します。
STATIC変数は「一意の実体」を共有するため、Aという処理が変数を書き換えている最中に、Bという処理が割り込んで同じ変数を書き換えると、Aの処理が想定していた値が消えてしまうという「データ競合」が発生します。
3. 実装/解決策:自動変数(スタック領域)への変更
STATIC変数の問題を解決する最も基本的な方法は、変数を自動変数(Automatic変数)として定義し直すことです。自動変数はプログラムが呼ばれるたびにスタック領域に確保されるため、スレッド(またはタスク)ごとに個別のメモリ領域が割り当てられ、他の処理と干渉しません。
4. サンプルプログラム:修正前と修正後
以下は、PL/Iにおける修正の例です。
/ 修正前:STATICを使うと全スレッドで同じ領域を参照してしまう /
DCL WORK_AREA CHAR(10) STATIC INIT(”);
/ 修正後:STATICを削除(デフォルトでAUTOMATICになる) /
DCL WORK_AREA CHAR(10);
/ 具体的なコード例 /
PROCEDURE_NAME: PROC;
/ この変数は呼び出しごとに個別に確保されるため安全 /
DCL CURRENT_ID CHAR(5);
/ 処理ロジック /
CURRENT_ID = ‘ID001’; / 他のスレッドの影響を受けない /
/ 処理の終了とともにメモリは解放される /
END PROCEDURE_NAME;
5. 応用・注意点:モダン環境への移行を見据えて
現代のメインフレーム開発では、Javaへの移行も増えています。Javaにおいて、メインフレームのSTATIC変数をそのまま `static` フィールドに変換すると、マルチスレッド環境で深刻なバグを引き起こします。
現場での回避策:
・可能であれば、変数はメソッド内の「ローカル変数」として定義する。
・どうしてもクラス全体で保持する必要がある場合は、`ThreadLocal` を使用するか、インスタンス変数(非static)として設計を修正する。
「STATIC=便利で速い」という古い認識を捨て、常に「この変数は並列実行されても安全か?」と自問自答することが、保守性の高いコードを作る近道です。

コメント