Mutexes in COBOL
In the previous example, we saw how to manage simple counter state using atomic operations. For more complex state, we can use a mutex to safely access data across multiple threads.
IDENTIFICATION DIVISION.
PROGRAM-ID. MUTEXES.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-CONTAINER.
05 WS-COUNTERS.
10 WS-COUNTER-A PIC 9(5) VALUE 0.
10 WS-COUNTER-B PIC 9(5) VALUE 0.
01 WS-MUTEX SYNC.
PROCEDURE DIVISION.
MAIN-PROCEDURE.
PERFORM INITIALIZE-CONTAINER
PERFORM START-THREADS
PERFORM DISPLAY-RESULTS
STOP RUN.
INITIALIZE-CONTAINER.
MOVE 0 TO WS-COUNTER-A
MOVE 0 TO WS-COUNTER-B.
START-THREADS.
CALL "CBL_CREATE_THREAD" USING
THREAD-MAIN-A
BY REFERENCE WS-CONTAINER
BY REFERENCE WS-MUTEX.
CALL "CBL_CREATE_THREAD" USING
THREAD-MAIN-A
BY REFERENCE WS-CONTAINER
BY REFERENCE WS-MUTEX.
CALL "CBL_CREATE_THREAD" USING
THREAD-MAIN-B
BY REFERENCE WS-CONTAINER
BY REFERENCE WS-MUTEX.
CALL "CBL_WAIT_ON_MULTIPLE_THREADS" USING 3.
DISPLAY-RESULTS.
DISPLAY "Counter A: " WS-COUNTER-A
DISPLAY "Counter B: " WS-COUNTER-B.
THREAD-MAIN-A.
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 10000
PERFORM INCREMENT-A
END-PERFORM.
THREAD-MAIN-B.
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 10000
PERFORM INCREMENT-B
END-PERFORM.
INCREMENT-A.
CALL "CBL_ENTER_CRITICAL_SECTION" USING WS-MUTEX
ADD 1 TO WS-COUNTER-A
CALL "CBL_EXIT_CRITICAL_SECTION" USING WS-MUTEX.
INCREMENT-B.
CALL "CBL_ENTER_CRITICAL_SECTION" USING WS-MUTEX
ADD 1 TO WS-COUNTER-B
CALL "CBL_EXIT_CRITICAL_SECTION" USING WS-MUTEX.
In this COBOL program, we define a container structure (WS-CONTAINER
) that holds two counters. Since we want to update it concurrently from multiple threads, we add a mutex (WS-MUTEX
) to synchronize access.
The INCREMENT-A
and INCREMENT-B
procedures lock the mutex before accessing the counters and unlock it afterward. This ensures that only one thread can modify the counters at a time.
In the START-THREADS
procedure, we create three threads: two that increment counter A and one that increments counter B. We use the CBL_CREATE_THREAD
call to start the threads and CBL_WAIT_ON_MULTIPLE_THREADS
to wait for them to finish.
Note that the zero value of a mutex is usable as-is in COBOL, so no initialization is required.
Running the program shows that the counters are updated as expected:
Counter A: 20000
Counter B: 10000
This example demonstrates how to use mutexes to safely manage shared state across multiple threads in COBOL. While COBOL doesn’t have built-in goroutines like Go, we can achieve similar concurrency using threads and synchronization primitives.
Next, we’ll look at implementing this same state management task using only threads and message passing.