Java Reference
In-Depth Information
2.2.2. Example: Race Conditions in Lazy Initialization
A common idiom that uses check-then-act is lazyinitialization . The goal of lazy initialization
is to defer initializing an object until it is actually needed while at the same time ensuring
that it is initialized only once. LazyInitRace in Listing 2.3 illustrates the lazy initializa-
tion idiom. The getInstance method first checks whether the ExpensiveObject has
already been initialized, in which case it returns the existing instance; otherwise it creates a
new instance and returns it after retaining a reference to it so that future invocations can avoid
the more expensive code path.
Listing 2.3. Race Condition in Lazy Initialization. Don't do this.
LazyInitRace has race conditions that can undermine its correctness. Say that threads A
and B execute getInstance at the same time. A sees that instance is null , and in-
stantiates a new ExpensiveObject . B also checks if instance is null . Whether in-
stance is null at this point depends unpredictably on timing, including the vagaries of
scheduling and how long A takes to instantiate the ExpensiveObject and set the in-
stance field. If instance is null when B examines it, the two callers to getIn-
stance may receive two different results, even though getInstance is always supposed
to return the same instance.
The hit-counting operation in UnsafeCountingFactorizer has another sort of race
condition. Read-modify-write operations, like incrementing a counter, define a transforma-
tion of an object's state in terms of its previous state. To increment a counter, you have to
Search WWH ::




Custom Search