Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
The ThreadLocal class, introduced in JDK 1.2, can help reduce some of the complexities involved in developing thread-safe classes by reducing
the amount of data shared between threads. But as we shall see, sometimes this simplicity results in performance costs. Let's
review the DCL problem and then look at how you can use ThreadLocal to solve part of that problem.
DCL is a technique for lazy initialization; it attempts to eliminate the synchronization overhead on the most common code path when fetching a reference to the lazily initialized object. Developers often try to avoid synchronizing on the common code path because of efficiency issues -- synchronized operations run more slowly than unsynchronized ones. Here is an example of the (incorrect) DCL idiom and the (correct) single-check idiom it was intended to replace:
Listing 1. The double-checked locking (DCL) idiom
// This class is not thread-safe
class DoubleCheckExample { // Not thread-safe
private static Resource resource = null;
public static Resource getResource() {
if (resource == null) {
synchronized {
if (resource == null)
resource = new Resource();
}
}
return resource;
}
}
// This class is thread-safe
class SingleCheckExample {
private static Resource resource = null;
public static Resource getResource() {
synchronized {
if (resource == null)
resource = new Resource();
}
}
return resource;
}
}
Note that in SingleCheckExample, you must execute a synchronized block every time getResource() is called, whereas in DoubleCheckExample, you have to synchronize only the first time. While it appears harmless, DCL doesn't work because the JMM doesn't guarantee
that other threads will necessarily see updates to variables made by other threads, unless both threads synchronize on the
same monitor. Without synchronizing when you access the shared variable (the resource field), under some architectures and with some unlucky timing, another thread could see a partially constructed Resource returned from getResource(). DCL falls afoul of the synchronization rules by having the first reference to resource, the check to see if it is null, appear outside the synchronized block. In order to guarantee that the Resource object is fully constructed before it is made visible to other threads, you must synchronize.