Using a Mutex

The simplest form of a data sharing problem is when multiple threads require mutually exclusive access to shared data at some point during their processing. The area of code that accesses this shared data is called a critical section and these critical sections can be protected by the use of a mutex that is logically associated with the shared data items. The term mutex comes from the phrase mutual exclusion. The mutex associated with the data items is locked before a critical section is entered and unlocked when that critical section is finished.

It is vital that all threads lock the mutex before accessing any of the data that is being protected. If even one thread fails to follow this regime, then unpredictable results could occur.

For example, the following code illustrates the protection of two critical sections that access a table, adding to it or counting items in it. The working storage data items table-xxx are protected by table-mutex.

Example

In this example the mutex is required to prevent a thread from adding data to the table while another thread reads the table at the same time.

 Working-Storage Section.
 78  table-length        value 20.
 01  table-mutex         usage mutex-pointer.
 01  table-current       pic x(4) comp-x value 0.
 01  table-max           pic x(4) comp-x value 0.
 01  table-1.
    05  table-item-1     pic x(10) occurs 20.

 Local-Storage Section.
 01  table-count         pic x(4) comp-x.
 01  table-i             pic x(4) comp-x.

* Initialization code executed while in single-threaded mode
     move 0 to table-max
     open table-mutex

* Add an item to table-1, this is a critical section
     set table-mutex to on
     if table-current < table-length
         add 1 to table-current
         move 'filled in' to table-item-1(table-current)
     end-if
     set table-mutex to off

* Count items in table-1, this is a critical section
     set table-mutex to on
     move 0 to table-count
     perform varying table-i from 1 by 1 
             until table-i > table-current
         if  table-item-1(table-i) = 'filled in'
             add 1 to table-count
         end-if
     end-perform
     set table-mutex to off

One problem with using a mutex is that it can severely limit the level of multi-threading within an application. For example, say you have an application in which some programs add items to a table or count items in a table. In order to maximize multi-threading, you would want multiple threads to be able to count items in the table simultaneously. However, if a program was adding items to a table, you would not want a program to add items or count them.

A solution to this problem would be given by a synchronization primitive that enables multiple threads to be active in read-only critical sections but prevents any other access when a thread is active in a writer critical section; such a synchronization primitive is the monitor.