A wrapper for objects that are not thread-safe. Such objects
have methods that cannot safely be executed concurrently in
multiple threads. To use an unsafe object within a parallel
computation, first construct an instance of this wrapper.
Then, within the compute method, get the unsafe object; if
null, construct and set a new unsafe object in this wrapper,
before using the unsafe object to perform the computation.
This pattern ensures that each thread computes using a
distinct unsafe object. For example,
final Parallel.Unsafe<Worker> nts = new Parallel.Unsafe<Worker>();
Parallel.loop(count,new Parallel.LoopInt() {
public void compute(int i) {
Worker w = nts.get(); // get worker for the current thread
if (w==null) nts.set(w=new Worker()); // if null, make one
w.work(); // the method work need not be thread-safe
}
});
This wrapper is most useful when (1) the cost of constructing an
unsafe object is high, relative to the cost of each call to compute,
and (2) the number of threads calling compute is significantly
lower than the total number of such calls. Otherwise, if either
of these conditions is false, then simply construct a new unsafe
object within the compute method.
This wrapper works much like the Java standard class ThreadLocal,
except that an object within this wrapper can be garbage-collected
before its thread dies. This difference is important because
fork-join worker threads are pooled and will typically die only
when a program ends.