In SPARC machines, the test and set instruction is ldstub ("load and store unsigned byte"),
which loads a byte into a register while setting that byte to all ones. Code Example 6-2 shows how
it can be used to create a basic lock. The important thing to understand here is that no matter how
many different threads on how many different CPUs call ldstub at the same time, only one of
them will get ownership. Exactly how the go_to_sleep function works is unimportant. Indeed,
even if it did nothing at all and just jumped right back to try_again, the locking code would still
work (see Spin Locks). Notice that there is no guarantee that a thread that goes to sleep will get
the lock when it wakes up.
Example 6-2 Pseudo-assembly Code for the Mutual Exclusion Lock
ldstub address -> register
compare register, 0
Other types of atomic instructions are used on other machines, most of which are logically
equivalent. The one type of instruction that is substantially different is the compare and swap
instruction, which compares one word of main memory with a register and swaps the contents of
that word with a second register when equal. This type of instruction allows some other types of
and Swap), giving significantly superior performance for specific situations.
A critical section is a section of code that must be allowed to complete atomically with no
interruption that affects its completion.
We create critical sections by locking a lock (as in Code Example 6-2), manipulating the data,
then releasing the lock afterward. Such things as incrementing a counter or updating a record in a
database need to be critical sections. Other things may go on at the same time, and the thread that
is executing in the critical section may even lose its processor, but no other thread may enter the
critical section. Should another thread want to execute that same critical section, it will be forced
to wait until the first thread finishes.
Critical sections are typically made as short as possible and often carefully optimized because they
can significantly affect the concurrency of the program. As with all the code in this topic, we rely
upon the programmer to obey the rules for using critical sections. There is no external
enforcement that prevents a sloppy programmer from manipulating data without holding the proper
Lock Your Shared Data!
All shared data must be protected by locks. Failure to do so will result in truly ugly bugs. Keep in
mind that all means all. Data structures that are passed to other threads and global variables are the
obvious examples. All data structures that can be accessed by multiple threads are included.
Static variables are included.
It is, of course, possible to have global variables that are not shared, but this would be rather
unusual. Be very careful if you think you have one. If you're wrong, you're going to be unhappy
when something breaks.
Search WWH :