ジョブ、タスク、スレッド その2
ジョブ関連の用語の説明の続き
- 6 スレッド
-
NEC公式のシステム管理説明書には、スレッドについて次のように記載しています。
スレッドとは、ジョブ管理がジョブの流れを制御するための単位です。
スレッドは、操作開始コマンド、画面切離コマンドなどが入力された後、最初のジョブが起動されたときに生成され、最初のジョブに続く一連のジョブの実行が終了したときに消滅します。
つまり、スレッドとは、ジョブの流れ(ジョブストリーム)を1 つの管理単位としてとらえた場合の表現にあたります。
[システム管理説明書(2009年11月版)−2.2.1 スレッド・ジョブ・ジョブステップ・タスク]より私は、スレッドのことをジョブを入れる器と考えています。ここではシステム管理説明書の説明を「器」を使って説明してみたいと思います。
- 6.1 スレッドの生成
-
スレッドの生成についてマニュアルの内容を引用すると
スレッドは、ワークステーション(WS)から操作開始コマンド、画面切離コマンド、優先処理コマンドがが入力されたとき、あるいは 〜中略〜 ときに生成されます
[システム管理説明書(2009年11月版)−2.3.1 スレッドの生成と開始]より私が調べた限りでは、スレッドが生成される場合は以下の場合のようです。
- 操作開始コマンドを入力
- 画面切離コマンドを入力
- 優先処理コマンドを入力
- ワークステーション対応初期プログラムが定義されている端末(PC/WSエミュレータ)が起動したとき
- COBOLシステムサブルーチン:SPAWNマクロでジョブを実行した場合
操作開始コマンドや画面切離コマンドを行ったときに、1つ空の「器」ができると考えます。
もう一つスレッドが生成されたときに行われることとして、
スレッドが生成されたときには、スレッドを生成したWS はそのスレッドによって所有されます。
[システム管理説明書(2009年11月版)−2.3.1 スレッドの生成と開始]よりつまり端末の画面に生成した「スレッドの画面」が表示される、ということです。
「器」のたとえで説明すると、「器」と端末がつながって、「器」の内容が表示されるということです。生成した段階では「器」は空なので何も表示されず、RUNコマンドの入力画面になります。
- 6.2 スレッドの開始
-
マニュアルの内容の引用は長くなるので省略して、簡単に言うとRUNコマンドからジョブを実行したり、メニュー画面を表示しようとしたり、初期プログラムが実行されたりするとスレッドが開始されます。
スレッドの開始を「器」のたとえで言うと次の通りです。 「器」に実行するジョブが乗ります。実行する主体のジョブストリームやメニューが乗ります。使用するメモリ空間も「器」に乗ります。画面イメージも「器」に乗ります。さらにジョブ制御変数(JRCODE)、センススイッチなどの情報が初期化されて「器」に乗ります。初期化が終わるとジョブストリームの先頭からジョブの実行が始まります。
「器」と端末がつながっているので「器」の内容(つまり「器」に乗っている画面イメージ)が画面に表示されます。ジョブを実行した場合はジョブの内容が画面に表示されます。メニューの場合はメニュー画面が表示されることになります。
- 6.3 ジョブの実行中
-
ジョブストリームの先頭からジョブが実行されます。ジョブ制御変数やセンススイッチの情報を変更する場合は、同じ「器」に乗っているジョブ制御変数やセンススイッチの情報を変更します。
ロードモジュールを実行する場合は、まず同じ「器」に乗っているメモリ空間にロードモジュールの内容を展開し、ロードモジュール内の命令を順次実行します。
ロードモジュールのデータ部も同じ「器」のメモリ空間を使用します。常に同じ「器」の中のメモリ空間を使用するので、別の「器」のメモリ空間内のデータを使用したり壊してしまったりということはありません。
一時ファイルを使用する場合は、一時ファイルの情報も「器」に乗ります。一時ファイルも「器」毎に乗るので、別の「器」の一時ファイルを読み書きすることはできません。たとえ同じファイル名でも「器」が別なので、別の一時ファイルになります。
ロードモジュールの実行が終了したときはメモリ空間の内容を破棄します。命令部とデータ部の内容をクリアするということです。次にまたロードモジュールを実行する場合はまたメモリ空間にそのロードモジュールの内容を展開して実行することになります。
ジョブストリームで//文が実行したり、ロードモジュール(COBOLプログラム)のWRITE命令で画面に表示を行おうとした場合、まず「器」の中にある画面イメージが更新されます。次に「器」と端末がつながっていた場合は更新した画面イメージを端末の画面に表示します。
「器」が端末とつながっていない場合は画面イメージを端末に表示することができないので、ジョブは画面表示待ちで一時的に止まった状態になります。このとき端末の画面の右下に画面表示待ちのジョブがいることを示す「*」のマークが表示されます。
端末のキーボードから入力した情報もつながっているスレッドに伝わります。そのスレッドで動いているジョブ、ロードモジュールに入力した情報が伝わることになります。
- 6.4 スレッドの終了
-
スレッドの終了についてマニュアルの内容の引用
スレッドは、それらに続く一連のジョブの流れが終了したときに終了します。
ジョブの流れは、次の場合に終了します。
- ジョブプログラムの実行が終了した場合
- ワークステーション(WS)から業務放棄/操作終了コマンドが入力された場合
- WS からプログラム放棄コマンドが入力されたときが、ジョブの流れの最終ジョブステップだった場合
[システム管理説明書(2009年11月版)−2.3.2 スレッドの終了と消滅]よりジョブが終了した場合は、スレッドも終了となり、「器」に乗っていた一時ファイルやジョブストリームが解放されます。
ジョブ制御変数、センススイッチはまだ残るようです。
- 6.4 スレッドの消滅
-
スレッドの消滅はマニュアルはいろいろと複雑なことが書かれていますが、次のようなことだと思っています。
引き続きスレッドを「器」と表して説明します。
端末につながることの可能な「器」が他にある場合には、まずその別の「器」を端末につなげます。そして終了した「器」の中身を適切に終了処理してから、「器」を消滅させます。(端末につながることが可能な「器」については後述。)
端末につながることの可能な「器」がない場合は、終了した「器」を再利用します。メニューや初期プログラムが設定されている場合は、メニューや初期プログラムを再利用の「器」に乗せます。
スレッド(「器」)を再利用する場合があるということは要注意です。バグなのか何なのか、ジョブ制御変数、センススイッチの状態が初期化されず、前のジョブの最終状態のままのことがありました。
- 6.5 メニューからジョブを実行する場合
-
メニューからジョブを選んでジョブを実行する場合、ジョブ実行=スレッドの開始 ではないことに注意が必要です。メニューの画面が表示された時点でスレッドは開始しています。ジョブの実行中の扱いです。
「器」に乗ったメニューを降ろして、ジョブストリームを乗せて、ジョブストリームの最初から実行します。すでに「器」に乗っている画面イメージやジョブ制御変数、センススイッチの状態はそのままです。なので画面を更新したり消去したりしないと画面は前のままの状態を保ちます。ジョブ制御変数、センススイッチの状態も同様です。
- 7 端末とスレッドの関係
-
システム管理説明書には、端末(WS)とスレッドについて次のように記載しています。
WSの接続
スレッドが生成されたときには、スレッドを生成したWSはそのスレッドによって所有されます。このWSが所有されている状態を”WSがスレッドに接続されている”といいます。
1台のWSで複数のジョブを実行することが可能ですが、操作開始/画面切離/優先処理コマンドによって新しくスレッドが生成されたときには、その時点でWSは新しいスレッドに所有され、元のスレッドはWSから切り離された状態になります。
〜中略〜
画面接続コマンドを入力して、そのスレッドにWSを接続することで 〜後略〜
[システム管理説明書(2009年11月版)−2.3.1 スレッドの生成と開始]より私の「器」の話では次のようになります。
- 7.1 操作開始コマンド入力
-
操作開始でスレッドAが生成されます。メニューを実行すればスレッドAが開始されます。端末とスレッドAが接続されてメニュー画面を表示します。
操作開始で「器A」ができます。メニューを実行すると「器A」に諸々のものが乗ります。端末と「器A」がつながって、「器A」に乗っている画面イメージ、つまりメニューの画面が表示されます。
- 7.2 画面切離コマンド入力
-
画面切離でスレッドBが生成されます。プログラムを実行すればスレッドBが開始されます。端末とスレッドBが接続されてプログラムの画面を表示します。
「器」で説明します。
画面切離で「器B」ができます。プログラムを実行すると「器B」に諸々のものが乗ります。端末と「器B」がつながって、「器B」に乗っている画面イメージ、つまりプログラムの画面が表示されます。
新しいジョブを実行する為には新しいスレッドを用意する必要があります。画面切離コマンドとは、新しいスレッドを生成して、そのスレッドを操作するために、いままでつながっていたスレッドを「切り離し」て新しいスレッドに接続するためのコマンドです。切り離しが目的ではなく、新しいスレッドに接続する為のコマンドです。
「器A」はどこへ行った?
端末は1つの「器」としかつながりません。端末1つに画面は1つなので、どれかの「器」の画面イメージを表示することしかできません。
端末と「器B」をつなげるために、「器A」は端末と切り離されます。
- 7.3 端末と切り離されたスレッドはどうなるか?
-
端末とスレッドが切り離されても、スレッドが無くなったりジョブが止まったりはしません。スレッド内のジョブは動き続けます。
俗に「ジョブが裏で動いている状態」とか言います。
但し、ジョブが一時停止することもあります。
- 一時停止のコマンドが実行されたとき
- 画面に対して入出力されたとき
上の一時停止のコマンドとは、JCLの/PAUSEコマンドやCOBOLの一時停止の命令などです。
画面に対して入出力とは、キーボードからの入力とか画面上に何かを表示しようとしたとか、です。画面上に何か表示しようとしても、スレッドと端末が切り離されているので端末の画面に表示できません。キーボードから何か入力させようとしても、スレッドと端末が切り離されているので端末のキーボードから入力できません。
「器」の例で言うと、「器」の上に乗っている画面イメージが更新されたときに、端末の画面を画像イメージに更新しようとしたが、端末と「器」がつながっていないので、つながるまで待ちます、ということになります。
キーボードからの入力や画面に表示しようとしたら止まるなら、すぐに止まるのではないか、と思う人もいるかもしれません。
インタラクティブジョブ(会話型ジョブ)は、そもそもキーボード入力や画面表示のためのジョブなので、裏にいるあいだは止まるのが普通です。
バッチジョブの場合は、ひたすらデータ抽出、ソート、ファイル入出力といったデータ処理を行うことが普通なので、その間は画面表示やキー入力しないのが普通です。画面表示やキー入力がないのなら止まることはありません。
バッチで画面に対しての入出力するとしたら、バッチジョブ起動直後に条件を入力させたり「ジョブ開始します」と表示させたり、バッチ終了時に「終了しました。xx件処理しました」とか程度でしょう。バッチ実行中はあまり表示させません。
ちなみに実行中に「xx件中yy件処理しました」みたいなのを表示しようとすると、通常は止まります。ちゃんと裏で動作しているときは止まらないようにする方法もあって、COBOLのDISPLAY命令でBYPASS MODEを使用します。
- 7.4 画面接続コマンド入力
-
画面切離状態のスレッド(俗に「裏で動いているジョブ」)の画面を見るにはどうすればよいかですが、これは画面接続コマンドを使います。
例えば、スレッドAとスレッドBの2つのスレッドがあり、今はスレッドBと端末が接続されているとします。
端末に接続されているのはスレッドBなので、スレッドBの画面が端末に表示されています。
ここで画面接続コマンドを入力すると端末とスレッドBが切り離されて、スレッドAがつながります。するとスレッドAの画面が端末に表示されることになります。
A、B、C、Dの4つのスレッドがある場合は、画面接続コマンドを入力するたびに、A→B→C→D→A→B→C→D→A・・・と順番につながります。
ここで注意するべきことは別の端末で生成されたスレッドは接続できないことです。
例えば2つの端末、端末a、端末bがあり、端末aでA、B、C、Dの4つのスレッドが生成されていて、端末bでE、Fの2つのスレッドが生成されていた場合を考えます。
端末aで画面接続コマンドを入力するとA→B→C→D→A→B・・と自分の端末で生成したスレッドしか接続できません。同様に端末bもE→F→E→F→・・・と自分の端末で生成したスレッドしか接続できません。
このようにある端末につながることの可能なスレッドは、その端末で生成したスレッドのみです。
考えてみればわかると思いますが、画面接続コマンドを入力したら、別の端末で操作している人の画面が出てきたらびっくりしますよね。別の人が操作している画面が出たらセキュリティ上も問題あります。
- 7.5 スレッドが終了/消滅するとき
-
スレッドが終了/消滅するときについては上で説明しましたが、もう一度端末とスレッドの関係で説明します。
端末につながっているスレッドが終了したとき、ほかに端末につながることの可能なスレッドがあるときは、端末にそのスレッドをつなげて、終了したスレッドは消滅します。
端末につながっているスレッドが終了したとき、ほかに端末につながることの可能なスレッドが無いときは、スレッドを消滅させずに流用します。
端末につながっていないスレッドが終了したときはどうなるか。
端末につながっているスレッドが別にあるので、つながっていなければそのまま消滅します。
OCFありのシステムの場合はもうちょっと複雑になりますが、うえで説明した単純なシステムと考え方は同じです。
スレッドはあくまでもジョブを実行するための入れもの/器で、スレッド上で実際に実行するものはジョブです。次にジョブをもう少し深堀していきます。