Java Reference
In-Depth Information
A constructor normally does not have to worry about issues of thread safety. Until the
constructor returns, no thread has a reference to the object, so it's impossible for two
threads to have a reference to the object. (The most likely issue is if a constructor depends
on another object in another thread that may change while the constructor runs, but
that's uncommon. There's also a potential problem if a constructor somehow passes a
reference to the object it's creating into a different thread, but this is also uncommon.)
You can take advantage of immutability in your own classes. It's usually the easiest way
to make a class thread safe, often much easier than determining exactly which methods
or code blocks to synchronize. To make an object immutable, simply declare all its fields
private and final and don't write any methods that can change them. A lot of classes in
the core Java library are immutable (e.g., java.lang.String , java.lang.Integer ,
java.lang.Double , and many more). This makes these classes less useful for some
purposes, but it does make them a lot more thread safe.
A third technique is to use a thread-unsafe class but only as a private field of a class that
is thread safe. As long as the containing class accesses the unsafe class only in a thread-
safe fashion and as long as it never lets a reference to the private field leak out into
another object, the class is safe. An example of this technique might be a web server that
uses an unsynchronized LogFile class but gives each separate thread its own separate
log so no resources are shared between the individual threads.
In some cases, you can use a designedly thread-safe but mutable class from the
java.util.concurrent.atomic package. In particular, rather than using an int , you
can use an AtomicInteger . Rather than using a long , you can use an AtomicLong . Rather
than using a boolean , you can use an AtomicBoolean . Rather than using an int[] , you
can use an AtomicIntegerArray . Rather than a reference variable, you can store an
object inside an AtomicReference , though note well that this doesn't make the object
itself thread safe, just the getting and setting of the reference variable. These classes may
be faster than synchronized access to their respective primitive types if they can take
advantage of fast machine-level thread-safe instructions on modern CPUs.
For collections such as maps and lists, you can wrap them in a thread-safe version using
the methods of java.util.Collections . For instance, if you have a set foo , you can
get a thread-safe view of this set with Collections.synchronizedSet(foo) . If you have
a list foo , you'd use Collections.synchronizedList(foo) instead. For a map, call
Collections.synchronizedMap(foo) , and so forth. In order for this to work, you must
henceforth use only the view returned by Collections.synchronizedSet/List/Map .
If at any point you access the original, underlying data structure, neither the original
nor the synchronized view will be thread safe.
In all cases, realize that it's just a single method invocation that is atomic. If you need to
perform two operations on the atomic value in succession without possible interruption,
you'll still need to synchronize. Thus, for instance, even if a list is synchronized via
Search WWH ::




Custom Search