逐次化されたプロシージャーを使用する場合

逐次化されたプロシージャーを使用して、共用リソースへのアクセスを同期化することができます。 共用リソースがジョブ内の他の場所で使用される場合、追加の手動同期の追加が 必要になる場合があります。

以下の例では、グローバルな all-thread 静的変数がファイルからロードされ、 アプリケーションでのその他の使用はすべて変数の値を参照するだけです。 同時に複数のスレッドによって変更される可能性がある場合、または 1 つのスレッドが 値を使用している間に他のスレッドがその値を変更する可能性がある場合、all-thread 静的変数への アクセスを制御する必要があることを覚えておいてください。ただし、 「first-time-only setup」コードで一度だけ変更される変数の特殊なケースでは、逐次化されたプロシージャーは、複数のスレッドによるアクセスを制御するために十分です。すべてのスレッドが first-time-only setup プロシージャーを呼び出し、プロシージャー自身がローカルの all-thread 静的変数を使用して セットアップが行われたかどうかを追跡します。一度に 1 つのスレッドのみがプロシージャーを実行する ようにプロシージャーが逐次化されるため、逐次化されたプロシージャーでローカルの all-thread 静的変数へのアクセスを制御するための手動同期は必要ありません。

getCustList プロシージャーは first-time-only setup プロシージャーの例です。 これが制御する共用リソースは、2 つのグローバルな all-thread 静的変数の ATS_custList および ATS_numCusts です。このプロシージャーは SERIALIZE キーワードで定義されます。これは、カスタマーのリストが含まれるファイルを読み取り、 そのリストを配列に保存します。これはローカルな all-thread 静的変数 ATS_done を使用して、 このリストが既に取得されたかどうかを追跡し、既に取得されている場合には、 即時に戻ります。リストが取得される前に、複数のスレッドが同時にプロシージャーを 呼び出そうとすると、1 つのスレッドが制御を取得し、他のスレッドは 最初のスレッドがプロシージャーを完了するまで待機します。 他のスレッドは、最終的に制御を取得すると、 ATS_done に値 *ON があることを検知するため、1 つずつ即時に戻ります。

 * !!! Warning !!!
 * These global ATS_xxx variables are in all-thread static storage.
 * They are setup in getCustList(). 
 * They should not be used before that procedure is called,
 * and they should not be changed after that procedure is called. 
D ATS_custList    S            100A   VARYING DIM(500)
D                                     STATIC(*ALLTHREAD)
D ATS_numCusts    S             10I 0 INZ(0)
D                                     STATIC(*ALLTHREAD)
 /free
       // Ensure that the all-thread static variables ATS_custList 
       // and ATS_numCusts have been set up
       getCustList();

       // Search for the customer name in the customer list
       if %lookup(custname : ATS_custList : 1 : ATS_numCusts);
         ...
 /end-free

P getCustList     B                   SERIALIZE
FcustList  IF   E             DISK            
D custInfo        DS                  LIKEREC(custRec)
 * ATS_done is shared by all threads running this procedure.
 * It doesn't need special thread-control because the procedure 
 * is serialized.
D ATS_done        S               N   INZ(*OFF)
D                                     STATIC(*ALLTHREAD)
 /free
      // Only load the customer array once
      if ATS_done;
         return;
      endif;
      // Fetch the list of customers into the ATS_custList array
      read custList custInfo;
      dow not %eof(custList);
         ATS_numCusts += 1;
         ATS_custList(ATS_numCusts) = %trim(custInfo.custName);

         read custList custInfo;
      enddo;

      // Set on the "first-time-only" indicator
      ATS_done = *ON;
 /end-free
P getCustList     E