Monitors provide a solution to particular access problems not handled easily by mutexes. For example, you might want many threads to be able to simultaneously read data, but only one thread to be able write data. While the thread writes data, you might want to block read access by other threads.
A monitor is used by a critical section to declare what type of data access the critical section will be performing on the protected data; that is, reading, writing, or browsing.
The monitor synchronization facility can be extended to provide a critical section for browsing; this can be very useful in real world applications. A browser reads data and, depending on conditions you have set, might or might not write to protected data items. While a browser is active, any number of critical sections that simply read the data are allowed, while any other critical sections that browse or write are not allowed. If the browser thread determines that it needs to write to the protected data, it requests a conversion of the browse lock to a write lock. The conversion process waits until all critical sections that read the data are finished, and then bars any other critical sections that read or write data from accessing the data. The browser proceeds to write with exclusive access to the protected data items (whose state is guaranteed to be the same as it was when the browser was just reading the protected data).
Example
The following example code shows a monitor that controls the access of multiple threads that count items in, or add items to, a table. The code:
Working-Storage Section.
78 table-length value 20.
01 table-monitor usage monitor-pointer.
01 table-current pic x(4) comp-x value 0.
01 table-1.
05 table-item-1 pic x(10) occurs table-length.
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-current
open table-monitor
* Add an item to table-1, this is a writer critical section
set table-monitor to writing
if table-current < table-length
add 1 to table-current
move 'filled in' to table-item-1(table-current)
end-if
set table-monitor to not writing
* Count items in table-1, this is a reader critical section
set table-monitor to reading
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-monitor to not reading
Example
The following is an example of a browser critical section:
Working-Storage Section.
01 data-monitor usage monitor-pointer.
01 data-value pic x(4) comp-x value 0.
* Initialization code, executed while in single threaded
* mode
open data-monitor
* Add an item to table-1, this is a browser critical section
set data-monitor to browsing
if data-value < 20
set data-monitor to writing
converting from browsing
add 5 to data-value
set data-monitor to not writing
else
set data-monitor to not browsing
end-if
We do not recommend that you use a browse lock for such a simple check. Usually, you need only use a browser if a significant amount of work has to be done to determine if a write lock is actually required, and you want to maximize multi-threading throughout your application. There are various other monitor conversions available to help you maximize the level of multi-threading in your application