If you think THREAD(*SERIALIZE) makes your module threadsafe, you're mistaken. It simply protects your module's static storage from being used by more than one thread at a time.
When you code THREAD(*SERIALIZE) in an RPG module, the RPG compiler generates code to ensure that only one thread is active in any procedure in that module at any time. A thread is considered active in a module if the call stack has a call made by the thread to any procedure in the module. (You can see the call stack by using option 11 of DSPJOB.)
For example, if thread #1 is running procA in moduleX and thread #2 tries to call procA or procB or any other procedure in moduleX, thread #2 has to wait until thread #1 has returned from procA. If procA was called from another procedure, say procC, in moduleX, then thread #2 has to wait until thread #1 returns from procC.
If procA makes a call to a procedure in another module, moduleY, then thread #1 is still considered to be active in moduleX. No other thread can call a procedure in either moduleX or moduleY until thread #1 has returned from all procedures in both modules.
By preventing more than one thread from being active in a module at once,
THREAD(*SERIALIZE) protects the static storage in the module from being accessed by more than one thread at once. This is true even if the static storage is passed as a reference parameter to a procedure in another module, since the calling procedure is still considered active.
Here's what you must do to make your application threadsafe:
1. Code THREAD(*SERIALIZE) on every module used by your application, including general-purpose service programs.
2. Ensure you do not call anything that is not threadsafe. This includes all OPM RPG programs.
3. Ensure that you do not have a situation in which two modules have static pointers to the same storage. If that happens, it is possible for two different threads to access the same storage, even if THREAD(*SERIALIZE) is coded in both modules. This could even happen with static storage if a procedure in moduleA passed a parameter to a procedure in moduleB, and the moduleB procedure saved the address of the parameter in a static variable. Another, more plausible way that this could happen is with a service program that allocates storage for several modules. Both the service program and the calling modules might have pointers to the allocated storage. If it is necessary to share storage across modules, additional coding is required to ensure that only one thread uses the storage at once. (How to do this is beyond the scope of this tip, but it would involve some mechanism such as a semaphore. This is discussed in the iSeries Information Center under Programming->Programming support->Multithreaded applications.)
Barbara Morris joined IBM in 1989 after graduating from the University of Alberta with a degree in computing science. Within IBM, she has always worked on the RPG Compiler team. You can contact Barbara at
TechTip: Make Your Application Threadsafe
Typography
- Smaller Small Medium Big Bigger
- Default Helvetica Segoe Georgia Times
- Reading Mode
LATEST COMMENTS
MC Press Online