A set of synchronization functions is provided which ensure order of memory between operations in different threads. These are ensure-loads-after-loads, ensure-memory-after-store, ensure-stores-after-memory and ensure-stores-after-stores.
Note: You should have a good understanding of multiprocessing issues at the CPU level to write code that actually needs these functions.
The effect of each of these functions is to ensure that all the operations of the first type (the word following the
ensure-
) that are in the program after the call to the function are executed after all the operations of the second type (last word in the function name) that are in the program before the call to the function.
Before or after "in the program" means the order that a programmer interpreting (correctly) the program would expect the operations to be executed. On a modern CPU this is not necessarily the same as the actual execution order. On a single CPU the end result is guaranteed to be the same, but on a computer with multiple CPU cores it is not.
An operation of type
load
is an operation that reads data from an object into a local variable. Typical
load
operations are
car
,
cdr
,
svref
, structure accessors,
slot-value
and getting the value of a symbol. A
store
operation is an operation that modifies data in an object. A
memory
operation is either a
load
or a
store
.
You need these functions when you need to synchronize between threads and you do not want to use the system supplied synchronization objects (Locks, mailboxes, Condition variables, Counting semaphores, Synchronization barriers). In most cases you should try first to use a synchronization object. Using the synchronization functions described in this section is useful if you can identify a serious bottleneck in your code that can be optimized using them.
For simple cases you should consider whether with-modification-check-macro and with-modification-change gives you the functionality you need.