An event is similar to a semaphore in that it enables one thread to signal to another that something has happened that requires attention. For several reasons an event is more flexible and slightly more complex. One reason is that an event, once posted, must be explicitly cleared.
Example
The following is an example of code that solves the Producer-Consumer problem by using event synchronization instead of semaphore synchronization:
Working-Storage Section. 01 produced-event usage event-pointer. 01 data-value pic x(4) comp-x value 0. 01 consumed-event usage event-pointer. * Initialization code executed while in single threaded mode open produced-event open consumed-event set consumed-event to true *> Initialize as 'posted' * Protocol for the producer side wait for consumed-event set consumed-event to false *> Clear event add 10 to data-value * Signal that data value has changed set produced-event to true *> Post event * Protocol for the consumer side, waiting for the data-value * to change wait for produced-event set produced-event to false *> Clear event display data-value * Signal other thread that it can proceed, this thread has * data-value set consumed-event to true *> Post event
If there are only two threads (the producer and consumer threads) executing the above code, then everything will work as expected. If another thread comes in and starts executing as a producer or consumer, unexpected events will occur. This is because an event, once posted, wakes up all threads waiting for that event, unlike a semaphore which enables only one thread to pass after the semaphore has been released. After an event has been posted, and the waiting threads are woken, it is necessary for each of the woken threads to determine if it should take some form of action on the event (including clearing the event).
The last point can make events difficult to work with when there are multiple waiting threads but it also enables the building of custom synchronization objects for special needs.