Information Technology Reference
In-Depth Information
Although it might appear that this code ensures that p is initialized before
anotherComputation(p) is called to compute q , it does not. To maximize in-
struction level parallelism, the hardware or compiler may set pIsInitialized=
true before the computation to compute p has completed, and anotherComputation(p)
may be computed using an unexpected value.
How can we reason about thread interleavings when compilers and hardware
may reorder a thread's operations?
Structured synchronization. Given all of these challenges, multi-threaded
code can introduce subtle, non-deterministic, and unreproducible bugs. This
chapter describes a structured synchronization approach to sharing state in
multi-threaded programs. Rather than scattering access to shared state through-
out the program and attempting ad hoc reasoning about what happens when
the threads' accesses are interleaved in various ways, we structure the program
to facilitate reasoning about it and we use a set of standard synchronization
primitives to control access to shared state. This approach gives up some free-
dom, but if you consistently follow the rules we describe, then reasoning about
programs with shared state becomes much simpler.
The first part of this section elaborates on the challenges faced by multi-
threaded programmers and on why it is futile to try to reason about all possible
thread interleavings in the general, unstructured case.
Challenges. Why are unstructured multi-threaded programs dicult to
reason about?
The rest of the chapter describes how to structure shared objects in multi-
threaded programs so that we can reason about them. We will describe aspects
of this structure. First, we will structure a multi-threaded program's shared
state as a set of shared objects that encapsulate the shared state and that define
and limit how the state can be accessed. Second, to avoid ad hoc reasoning about
the interleavings of access to the state variables within a shared object, we will
describe how shared objects include a small set of synchronization primitives
like locks and condition variables to coordinate access to their state by different
threads. Third, to simplify reasoning about the code in shared objects, we will
describe a set of best practices for writing the code that implements each shared
object. Because the first two issues are so closely tied together, we address these
two issues in two main sections:
Shared objects and synchronization variables. How do we use
synchronization variables like locks and condition variables to construct
shared objects that encapsulate shared state?
Search WWH ::




Custom Search