When to use a serialized procedure

You can use a serialized procedure to synchronize access to a shared resource. You may need to add additional manual synchronization if the shared resources are used elsewhere in your job.

In the following example, a global all-thread static variable is loaded from a file once, and all other uses in the application only refer to the value of the variable. Recall that it is necessary to control access to an all-thread static variable if it might be changed by multiple threads at the same time, or if one thread might be changing the value while another thread is using the value. However, in the special case of a variable that is changed only once in "first-time-only setup" code, a serialized procedure is sufficient to control the access by multiple threads. All threads call the first-time-only setup procedure, and the procedure itself uses a local all-thread static variable to keep track of whether the setup has already been done. No manual synchronization is required to control the access to a local all-thread-static variable in a serialized procedure, because the procedure is serialized to allow only one thread to be running the procedure at one time

The getCustList procedure is an example of a first-time-only setup procedure; the shared resources that it is controlling are two global all-thread-static variables, ATS_custList and ATS_numCusts. The procedure is defined with the SERIALIZE keyword. It reads a file containing a list of customers and saves the list in an array. It uses a local all-thread static variable, ATS_done, to keep track of whether the list has already been obtained, and if it has been obtained already, it returns immediately. If more than one thread tries to call the procedure at the same time before the list has been obtained, one thread will get control and the other threads will wait until the first thread has completed the procedure. When the other threads finally get control, one at a time, they will return immediately because they will find that ATS_done has the value *ON.

 * !!! 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


[ Top of Page | Previous Page | Next Page | Contents | Index ]