Java Reference
In-Depth Information
For each mutable state variable that may be accessed by more than one thread,
all
accesses to
that variable must be performed with the
same
lock held. In this case, we say that the variable
is
guarded by
that lock.
guarded by the servlet object's intrinsic lock; this is documented by the
@GuardedBy
an-
notation.
There is no inherent relationship between an object's intrinsic lock and its state; an object's
fields need not be guarded by its intrinsic lock, though this is a perfectly valid locking con-
vention that is used by many classes. Acquiring the lock associated with an object does
not
prevent other threads from accessing that object—the only thing that acquiring a lock pre-
vents any other thread from doing is acquiring that same lock. The fact that every object has
up to you to construct
lockingprotocols
or
synchronizationpolicies
that let you access shared
state safely, and to use them consistently throughout your program.
Every shared, mutable variable should be guarded by exactly one lock. Make it clear to main-
tainers which lock that is.
A common locking convention is to encapsulate all mutable state within an object and to
protect it from concurrent access by synchronizing any code path that accesses mutable state
using the object's intrinsic lock. This pattern is used by many thread-safe classes, such as
Vector
and other synchronized collection classes. In such cases, all the variables in an ob-
ject's state are guarded by the object's intrinsic lock. However, there is nothing special about
this pattern, and neither the compiler nor the runtime enforces this (or any other) pattern of
method or code path and forgetting to use synchronization.
Not all data needs to be guarded by locks—only mutable data that will be accessed from mul-
tiple threads. In
Chapter 1
, we described how adding a simple asynchronous event such as
a
TimerTask
can create thread safety requirements that ripple throughout your program,
especially if your program state is poorly encapsulated. Consider a single-threaded program
that processes a large amount of data. Single-threaded programs require no synchronization,
because no data is shared across threads. Now imagine you want to add a feature to create