Information Technology Reference
In-Depth Information
A program associates each lock with some subset of shared state and requires
a thread to hold the lock when accessing that state. Then, only one thread can
be accessing the shared state at a time.
Mutual exclusion greatly simplifies reasoning about programs because a
thread can perform an arbitrary set of operations while holding a lock, and
those operations appear to be atomic from the point of view of other threads. In
particular, because a lock enforces mutual exclusion and because threads must
hold the lock to access the shared state, no other thread will be able to observe
an intermediate|they can only observe the state left after the lock has been
released.
Example: Locking to group multiple operations. Consider, for example, a
bank account object that includes a list of transactions and a total balance. To
add a new transaction, we would acquire the account's lock, append the new
transaction to the list, read the old balance, modify it, write the new balance,
and release the lock. To query the balance and list of recent transactions, we
would acquire the account's lock, read the recent transactions from the list,
read the balance, and release the lock. Using locks this way would guarantee
that one update or query completes before the next one starts so that a query
always shows a balance that reflects the set of recent transactions shown.
It is much easier to reason about interleavings of atomic groups of operations
rather than interleavings of individual operations for two reasons. First, there
are (obviously) fewer interleavings to consider, so reasoning about interleavings
on a coarser-grained basis reduces the sheer number of cases we have to worry
about. Second, and more important, we can make each atomic group of oper-
ations correspond to the logical structure of the program, which allows us to
reason about invariants not specific interleavings.
In particular, with shared objects we usually use one lock to guard all of
an object's state, and we usually have each public method acquire the lock
on entry and release the lock on exit. Then, reasoning about a shared class's
code is similar to reasoning about a traditional class's code: we assume a set of
invariants when a public method is called and reestablish those invarients before
a public method returns. If we do a good job of defining our invariants, we can
then reason about each method largely independently.
5.3.1
Lock: API and properties
A lock enables mutual exclusion by providing two methods: Lock::acquire()
and Lock::release() . These operations are defined as follows:
A lock can be in one of two states:BusyorFree.
A lock is initially in theFreestate.
Search WWH ::




Custom Search