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.