


In the program that created it, a thread and its parent thread share the same data. This includes both working-storage and files (including the file's open state and record position). Thus any changes made in one thread will be seen by the other thread. The only data that are not shared are those items internally generated by the compiler that are related to the flow of control within a thread, such as a paragraph's return address or an internal counter associated with PERFORM "N" TIMES.
When a thread CALLs a program, any data local to that program are private to that thread (and its child threads). As a result, you can write utility routines that many threads can call, without having to worry about data sharing issues in the utility. Note that any data passed (BY REFERENCE) to the called program are shared if they are shared in the program passing the data.
External data items and external files are always shared by all threads.
ACUCOBOL-GT ensures that any one logical operation on a data item is fully completed before control switches between threads. Consider the following example:
77 DATA-1 PIC X(3).
PERFORM THREAD
MOVE "ABC" TO DATA-1
END-PERFORM
MOVE "DEF" TO DATA-1
WAIT FOR LAST THREAD
DISPLAY DATA-1
The last DISPLAY will either print "ABC" or "DEF" depending on the order in which the threads execute. It will not, however, print something like "AEF" or "DEC" because each MOVE that affects DATA-1 is performed in its entirety before control switches between threads.
LOCK THREAD and UNLOCK THREAD
There may be times when you want to be sure that a group of operations is performed without switching threads. For example, if you have a utility paragraph that does a series of math operations on a data item, you will not want to begin that paragraph and then switch to another thread if another thread uses that data item. In this case, you can use the LOCK THREAD statement to ensure that a series of operations are all accomplished together. For example:
PARA-1.
LOCK THREAD
ADD DATA-1 TO DATA-2
IF DATA-2 > DATA-2-DIV-LIMIT
MOVE DATA-2-DIV-LIMIT TO DATA-2
COMPUTE DATA-2 = DATA-2 / DATA-3
UNLOCK THREAD.
The LOCK THREAD statement ensures that no other thread executes. This condition remains in effect until the thread is unlocked (with UNLOCK THREAD) or the thread terminates. In the preceding example, if the LOCK THREAD was omitted, another thread referencing DATA-2 could see its value after the ADD but before the COMPUTE. This could be a value that is not meaningful.
A thread can have more than one lock. Each time a LOCK THREAD statement executes in the thread, the number of locks held by that thread increases by one. To allow other threads to run again, an equal number of UNLOCK THREAD statements must also execute. Each UNLOCK THREAD statement removes the last lock applied to the thread. This capability allows a thread to lock itself, call a subroutine that also locks itself, and remain locked after that subroutines unlocks itself.
The data sharing aspect of threads is very powerful. However, ensuring that the data are always consistent can be a difficult programming problem. When writing multithreaded programs, you should strive to share data in a well-defined manner to minimize this problem. The best way to do this is to share as little data as possible and to be clear when each thread is allowed to use that data.