Synchronization can be achieved by the various
functions with the appropriate
argument, but for simple cases of synchronization it is better to use the synchronization objects: condition variables or barriers. These synchronization objects are simple, efficient, deal with all thread safety issues, and ensure that the processes that are ready to run will run immediately, rather than the next time that the wait function is called.
Condition variables are used when one or more processes have the knowledge to control when another process(es) runs. The "ignorant" process(es) use condition-variable-wait to wait until they can continue. The "knowledgable" process(es) use condition-variable-signal and condition-variable-broadcast to tell the "ignorant" processes when they can run. Because the communication is via the condition variable, the processes do not need to know explicitly about each other. For more details, see Condition variables.
Barriers are used (mainly) for symmetric synchronization, when a group of processes needs to ensure that none of them goes too far ahead of the rest. The processes call barrier-wait when they want to synchronize, and barrier-wait waits until the other process arrive too (that is, they call barrier-wait). Barriers have additional features that allow more complex synchronization. For more details, see Synchronization barriers.