Java Reference
In-Depth Information
Chapter 3.
Sharing Objects
We stated at the beginning of
Chapter 2
that writing correct concurrent programs is primarily
about managing access to shared, mutable state. That chapter was about using synchronization
to prevent multiple threads from accessing the same data at the same time; this chapter exam-
ines techniques for sharing and publishing objects so they can be safely accessed by multiple
threads. Together, they lay the foundation for building thread-safe classes and safely structur-
ing concurrent applications using the
java.util.concurrent
library classes.
We have seen how
synchronized
blocks and methods can ensure that operations execute
atomically, but it is a common misconception that
synchronized
is
only
about atomicity or
demarcating “critical sections”. Synchronization also has another significant, and subtle, as-
pect:
memoryvisibility
. We want not only to prevent one thread from modifying the state of an
object when another is using it, but also to ensure that when a thread modifies the state of an
object, other threads can actually
see
the changes that were made. But without synchroniza-
tion, this may not happen. You can ensure that objects are published safely either by using ex-
plicit synchronization or by taking advantage of the synchronization built into library classes.
3.1. Visibility
Visibility is subtle because the things that can go wrong are so counterintuitive. In a single-
threaded environment, if you write a value to a variable and later read that variable with no
intervening writes, you can expect to get the same value back. This seems only natural. It may
be hard to accept at first, but when the reads and writes occur in different threads,
thisissimply
notthecase
. In general, there is
no
guarantee that the reading thread will see a value written by
another thread on a timely basis, or even at all. In order to ensure visibility of memory writes
across threads, you must use synchronization.
NoVisibility
in
Listing 3.1
illustrates what can go wrong when threads share data without
synchronization. Two threads, the main thread and the reader thread, access the shared vari-
ables
ready
and
number
. The main thread starts the reader thread and then sets
number
to 42 and
ready
to
true
. The reader thread spins until it sees
ready
is
true
, and then
prints out
number
. While it may seem obvious that
NoVisibility
will print 42, it is in
fact possible that it will print zero, or never terminate at all! Because it does not use adequate
synchronization, there is no guarantee that the values of
ready
and
number
written by the
main thread will be visible to the reader thread.