/* * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as explained at * http://creativecommons.org/publicdomain/zero/1.0/ */ package java.util.concurrent.atomic; /** * A set of methods providing fine-grained control over happens-before * and synchronization order relations among reads and/or writes. The * methods of this class are designed for use in uncommon situations * where declaring variables {@code volatile} or {@code final}, using * instances of atomic classes, using {@code synchronized} blocks or * methods, or using other synchronization facilities are not possible * or do not provide the desired control. * *
Memory Ordering. There are three methods for controlling * ordering relations among memory accesses (i.e., reads and * writes). Method {@code orderWrites} is typically used to enforce * order between two writes, and {@code orderAccesses} between a write * and a read. Method {@code orderReads} is used to enforce order * between two reads with respect to other {@code orderWrites} and/or * {@code orderAccesses} invocations. The formally specified * properties of these methods described below provide * platform-independent guarantees that are honored by all levels of a * platform (compilers, systems, processors). The use of these * methods may result in the suppression of otherwise valid compiler * transformations and optimizations that could visibly violate the * specified orderings, and may or may not entail the use of * processor-level "memory barrier" instructions. * *
Each ordering method accepts a {@code ref} argument, and * controls ordering among accesses with respect to this reference. * Invocations must be placed between accesses performed in * expression evaluations and assignment statements to control the * orderings of prior versus subsequent accesses appearing in program * order. These methods also return their arguments to simplify * correct usage in these contexts. * *
Usages of ordering methods almost always take one of the forms * illustrated in the examples below. These idioms arrange some of * the ordering properties associated with {@code volatile} and * related language-based constructions, but without other * compile-time and runtime benefits that make language-based * constructions far better choices when they are applicable. Usages * should be restricted to the control of strictly internal * implementation matters inside a class or package, and must either * avoid or document any consequent violations of ordering or safety * properties expected by users of a class employing them. * *
Reachability. Method {@code reachabilityFence} * establishes an ordering for strong reachability (as defined in the * {@link java.lang.ref} package specification) with respect to * garbage collection. Method {@code reachabilityFence} differs from * the others in that it controls relations that are otherwise only * implicit in a program -- the reachability conditions triggering * garbage collection. As illustrated in the sample usages below, * this method is applicable only when reclamation may have visible * effects, which is possible for objects with finalizers (see Section * 12.6 of the Java Language Specification) that are implemented in * ways that rely on ordering control for correctness. * *
Sample Usages * *
Safe publication. With care, method {@code orderWrites} * may be used to obtain the memory safety effects of {@code final} * for a field that cannot be declared as {@code final}, because its * primary initialization cannot be performed in a constructor, in * turn because it is used in a framework requiring that all classes * have a no-argument constructor; as in: * *
{@code * class WidgetHolder { * private Widget widget; * public WidgetHolder() {} * public static WidgetHolder newWidgetHolder(Params params) { * WidgetHolder h = new WidgetHolder(); * h.widget = new Widget(params); * return Fences.orderWrites(h); * } * }}* * Here, the invocation of {@code orderWrites} ensures that the * effects of the widget assignment are ordered before those of any * (unknown) subsequent stores of {@code h} in other variables that * make {@code h} available for use by other objects. Initialization * sequences using {@code orderWrites} require more care than those * involving {@code final} fields. When {@code final} is not used, * compilers cannot help you to ensure that the field is set correctly * across all usages. You must fully initialize objects * before the {@code orderWrites} invocation that makes * references to them safe to assign to accessible variables. Further, * initialization sequences must not internally "leak" the reference * by using it as an argument to a callback method or adding it to a * static data structure. If less constrained usages were required, * it may be possible to cope using more extensive sets of fences, or * as a normally better choice, using synchronization (locking). * Conversely, if it were possible to do so, the best option would be * to rewrite class {@code WidgetHolder} to use {@code final}. * *
An alternative approach is to place similar mechanics in the * (sole) method that makes such objects available for use by others. * Here is a stripped-down example illustrating the essentials. In * practice, among other changes, you would use access methods instead * of a public field. * *
{@code * class AnotherWidgetHolder { * public Widget widget; * void publish(Widget w) { * this.widget = Fences.orderWrites(w); * } * // ... * }}* * In this case, the {@code orderWrites} invocation occurs before the * store making the object available. Correctness again relies on * ensuring that there are no leaks prior to invoking this method, and * that it really is the only means of accessing the * published object. This approach is not often applicable -- * normally you would publish objects using a thread-safe collection * that itself guarantees the expected ordering relations. However, it * may come into play in the construction of such classes themselves. * *
Safely updating fields. Outside of the initialization * idioms illustrated above, Fence methods ordering writes must be * paired with those ordering reads. To illustrate, suppose class * {@code c} contains an accessible variable {@code data} that should * have been declared as {@code volatile} but wasn't: * *
{@code * class C { * Object data; // need volatile access but not volatile * // ... * } * * class App { * Object getData(C c) { * return Fences.orderReads(c).data; * } * * void setData(C c) { * Object newValue = ...; * c.data = Fences.orderWrites(newValue); * Fences.orderAccesses(c); * } * // ... * }}* * Method {@code getData} provides an emulation of {@code volatile} * reads of (non-long/double) fields by ensuring that the read of * {@code c} obtained as an argument is ordered before subsequent * reads using this reference, and then performs the read of its * field. Method {@code setData} provides an emulation of volatile * writes, ensuring that all other relevant writes have completed, * then performing the assignment, and then ensuring that the write is * ordered before any other access. These techniques may apply even * when fields are not directly accessible, in which case calls to * fence methods would surround calls to methods such as {@code * c.getData()}. However, these techniques cannot be applied to * {@code long} or {@code double} fields because reads and writes of * fields of these types are not guaranteed to be * atomic. Additionally, correctness may require that all accesses of * such data use these kinds of wrapper methods, which you would need * to manually ensure. * *
More generally, Fence methods can be used in this way to achieve * the safety properties of {@code volatile}. However their use does * not necessarily guarantee the full sequential consistency * properties specified in the Java Language Specification chapter 17 * for programs using {@code volatile}. In particular, emulation using * Fence methods is not guaranteed to maintain the property that * {@code volatile} operations performed by different threads are * observed in the same order by all observer threads. * *
Acquire/Release management of threadsafe objects. It may * be possible to use weaker conventions for volatile-like variables * when they are used to keep track of objects that fully manage their * own thread-safety and synchronization. Here, an acquiring read * operation remains the same as a volatile-read, but a releasing * write differs by virtue of not itself ensuring an ordering of its * write with subsequent reads, because the required effects are * already ensured by the referenced objects. * For example: * *
{@code * class Item { * synchronized f(); // ALL methods are synchronized * // ... * } * * class ItemHolder { * private Item item; * Item acquireItem() { * return Fences.orderReads(item); * } * * void releaseItem(Item x) { * item = Fences.orderWrites(x); * } * * // ... * }}* * Because this construction avoids use of {@code orderAccesses}, * which is typically more costly than the other fence methods, it may * result in better performance than using {@code volatile} or its * emulation. However, as is the case with most applications of fence * methods, correctness relies on the usage context -- here, the * thread safety of {@code Item}, as well as the lack of need for full * volatile semantics inside this class itself. However, the second * concern means that it can be difficult to extend the {@code * ItemHolder} class in this example to be more useful. * *
Avoiding premature finalization. Finalization may occur * whenever a Java Virtual Machine detects that no reference to an * object will ever be stored in the heap: A garbage collector may * reclaim an object even if the fields of that object are still in * use, so long as the object has otherwise become unreachable. This * may have surprising and undesirable effects in cases such as the * following example in which the bookkeeping associated with a class * is managed through array indices. Here, method {@code action} * uses a {@code reachabilityFence} to ensure that the Resource * object is not reclaimed before bookkeeping on an associated * ExternalResource has been performed; in particular here, to ensure * that the array slot holding the ExternalResource is not nulled out * in method {@link Object#finalize}, which may otherwise run * concurrently. * *
{@code * class Resource { * private static ExternalResource[] externalResourceArray = ... * * int myIndex; * Resource(...) { * myIndex = ... * externalResourceArray[myIndex] = ...; * ... * } * protected void finalize() { * externalResourceArray[myIndex] = null; * ... * } * public void action() { * try { * // ... * int i = myIndex; * Resource.update(externalResourceArray[i]); * } finally { * Fences.reachabilityFence(this); * } * } * private static void update(ExternalResource ext) { * ext.status = ...; * } * }}* * Here, the call to {@code reachabilityFence} is nonintuitively * placed after the call to {@code update}, to ensure that * the array slot is not nulled out by {@link Object#finalize} before * the update, even if the call to {@code action} was the last use of * this object. This might be the case if for example a usage in a * user program had the form {@code new Resource().action();} which * retains no other reference to this Resource. While probably * overkill here, {@code reachabilityFence} is placed in a {@code * finally} block to ensure that it is invoked across all paths in the * method. In a method with more complex control paths, you might * need further precautions to ensure that {@code reachabilityFence} * is encountered along all of them. * *
It is sometimes possible to better encapsulate use of * {@code reachabilityFence}. Continuing the above example, if it * were OK for the call to method update to proceed even if the * finalizer had already executed (nulling out slot), then you could * localize use of {@code reachabilityFence}: * *
{@code * public void action2() { * // ... * Resource.update(getExternalResource()); * } * private ExternalResource getExternalResource() { * ExternalResource ext = externalResourceArray[myIndex]; * Fences.reachabilityFence(this); * return ext; * }}* *
Method {@code reachabilityFence} is not required in * constructions that themselves ensure reachability. For example, * because objects that are locked cannot in general be reclaimed, it * would suffice if all accesses of the object, in all methods of * class Resource (including {@code finalize}) were enclosed in {@code * synchronized (this)} blocks. (Further, such blocks must not include * infinite loops, or themselves be unreachable, which fall into the * corner case exceptions to the "in general" disclaimer.) However, * method {@code reachabilityFence} remains a better option in cases * where this approach is not as efficient, desirable, or possible; * for example because it would encounter deadlock. * *
Formal Properties. * *
Using the terminology of The Java Language Specification chapter * 17, the rules governing the semantics of the methods of this class * are as follows: * *
The following is still under construction. * *
*
*
*
*
See the class-level documentation for further explanation * and usage examples. * * @param ref the reference. If null, this method has no effect. */ public static void reachabilityFence(Object ref) { if (ref != null) { synchronized (ref) {} } } }