Class Fences
- java.lang.Object
-
- java.util.concurrent.atomic.Fences
-
public class Fences extends Object
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 variablesvolatileorfinal, using instances of atomic classes, usingsynchronizedblocks 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
orderWritesis typically used to enforce order between two writes, andorderAccessesbetween a write and a read. MethodorderReadsis used to enforce order between two reads with respect to otherorderWritesand/ororderAccessesinvocations. 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
refargument, 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
volatileand 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
reachabilityFenceestablishes an ordering for strong reachability (as defined in thejava.lang.refpackage specification) with respect to garbage collection. MethodreachabilityFencediffers 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
orderWritesmay be used to obtain the memory safety effects offinalfor a field that cannot be declared asfinal, 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:
Here, the invocation ofclass 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); } }orderWritesensures that the effects of the widget assignment are ordered before those of any (unknown) subsequent stores ofhin other variables that makehavailable for use by other objects. Initialization sequences usingorderWritesrequire more care than those involvingfinalfields. Whenfinalis not used, compilers cannot help you to ensure that the field is set correctly across all usages. You must fully initialize objects before theorderWritesinvocation 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 classWidgetHolderto usefinal.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.
In this case, theclass AnotherWidgetHolder { public Widget widget; void publish(Widget w) { this.widget = Fences.orderWrites(w); } // ... }orderWritesinvocation 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
ccontains an accessible variabledatathat should have been declared asvolatilebut wasn't:
Methodclass 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); } // ... }getDataprovides an emulation ofvolatilereads of (non-long/double) fields by ensuring that the read ofcobtained as an argument is ordered before subsequent reads using this reference, and then performs the read of its field. MethodsetDataprovides 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 asc.getData(). However, these techniques cannot be applied tolongordoublefields 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
volatile. However their use does not necessarily guarantee the full sequential consistency properties specified in the Java Language Specification chapter 17 for programs usingvolatile. In particular, emulation using Fence methods is not guaranteed to maintain the property thatvolatileoperations 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:
Because this construction avoids use ofclass 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); } // ... }orderAccesses, which is typically more costly than the other fence methods, it may result in better performance than usingvolatileor its emulation. However, as is the case with most applications of fence methods, correctness relies on the usage context -- here, the thread safety ofItem, 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 theItemHolderclass 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
actionuses areachabilityFenceto 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 methodObject.finalize(), which may otherwise run concurrently.
Here, the call toclass 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 = ...; } }reachabilityFenceis nonintuitively placed after the call toupdate, to ensure that the array slot is not nulled out byObject.finalize()before the update, even if the call toactionwas the last use of this object. This might be the case if for example a usage in a user program had the formnew Resource().action();which retains no other reference to this Resource. While probably overkill here,reachabilityFenceis placed in afinallyblock 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 thatreachabilityFenceis encountered along all of them.It is sometimes possible to better encapsulate use of
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 ofreachabilityFence:public void action2() { // ... Resource.update(getExternalResource()); } private ExternalResource getExternalResource() { ExternalResource ext = externalResourceArray[myIndex]; Fences.reachabilityFence(this); return ext; }Method
reachabilityFenceis 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 (includingfinalize) were enclosed insynchronized (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, methodreachabilityFenceremains 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.
- [Definitions]
-
- Define sequenced(a, b) to be true if a occurs before b in program order.
- Define accesses(a, p) to be true if a is a read or write of a field (or if an array, an element) of the object referenced by p.
- Define deeplyAccesses(a, p) to be true if either accesses(a, p) or deeplyAccesses(a, q) where q is the value seen by some read r such that accesses(r, p).
- [Matching]
- Given:
- p, a reference to an object
- wf, an invocation of
orderWrites(p)ororderAccesses(p) - w, a write of value p
- rf, an invocation of
orderReads(p)ororderAccesses(p) - r, a read returning value p
- sequenced(wf, w)
- read r sees write w
- sequenced(r, rf)
- wf happens-before rf
- wf precedes rf in the synchronization order
- If (r1, w1) and (r2, w2) are two pairs of reads and writes, both respectively satisfying the above conditions for p, and sequenced(r1, r2) then it is not the case that w2 happens-before w1.
- [Initial Reads]
- Given:
- p, a reference to an object
- a, an access where deeplyAccesses(a, p)
- wf, an invocation of
orderWrites(p)ororderAccesses(p) - w, a write of value p
- r, a read returning value p
- b, an access where accesses(b, p)
- sequenced(a, wf);
- sequenced(wf, w)
- read r sees write w, and r is the first read by some thread t that sees value p
- sequenced(r, b)
- the effects of b are constrained by the relation a happens-before b.
- [orderAccesses]
- Given:
- p, a reference to an object
- f, an invocation of
orderAccesses(p)
- sequenced(f, w)
- f is an element of the synchronization order.
- [Reachability]
- Given:
- p, a reference to an object
- f, an invocation of
reachabilityFence(p) - a, an access where accesses(a, p)
- b, an action (by a garbage collector) taking
the form of an invocation of
p.finalize()or of enqueing anyReferenceconstructed with argument p
- sequenced(a, f)
- a happens-before b.
-
-
Method Summary
All Methods Static Methods Concrete Methods Modifier and Type Method Description static <T> TorderAccesses(T ref)Informally: Ensures that accesses (reads or writes) using the given reference prior to the invocation of this method occur before subsequent accesses.static <T> TorderReads(T ref)Informally: Ensures that a read of the given reference prior to the invocation of this method occurs before a subsequent use of the given reference with the effect of reading or writing a field (or if an array, element) of the referenced object.static <T> TorderWrites(T ref)Informally: Ensures that a use of the given reference with the effect of reading or writing a field (or if an array, element) of the referenced object, prior to the invocation of this method occur before a subsequent write of the reference.static voidreachabilityFence(Object ref)Ensures that the object referenced by the given reference remains strongly reachable (as defined in thejava.lang.refpackage documentation), regardless of any prior actions of the program that might otherwise cause the object to become unreachable; thus, the referenced object is not reclaimable by garbage collection at least until after the invocation of this method.
-
-
-
Method Detail
-
orderReads
public static <T> T orderReads(T ref)
Informally: Ensures that a read of the given reference prior to the invocation of this method occurs before a subsequent use of the given reference with the effect of reading or writing a field (or if an array, element) of the referenced object. The use of this method is sensible only when paired with other invocations oforderWrites(T)and/ororderAccesses(T)for the given reference. For details, see the class documentation for this class.- Parameters:
ref- the reference. If null, this method has no effect.- Returns:
- the given ref, to simplify usage
-
orderWrites
public static <T> T orderWrites(T ref)
Informally: Ensures that a use of the given reference with the effect of reading or writing a field (or if an array, element) of the referenced object, prior to the invocation of this method occur before a subsequent write of the reference. For details, see the class documentation for this class.- Parameters:
ref- the reference. If null, this method has no effect.- Returns:
- the given ref, to simplify usage
-
orderAccesses
public static <T> T orderAccesses(T ref)
Informally: Ensures that accesses (reads or writes) using the given reference prior to the invocation of this method occur before subsequent accesses. For details, see the class documentation for this class.- Parameters:
ref- the reference. If null, this method has no effect.- Returns:
- the given ref, to simplify usage
-
reachabilityFence
public static void reachabilityFence(Object ref)
Ensures that the object referenced by the given reference remains strongly reachable (as defined in thejava.lang.refpackage documentation), regardless of any prior actions of the program that might otherwise cause the object to become unreachable; thus, the referenced object is not reclaimable by garbage collection at least until after the invocation of this method. Invocation of this method does not itself initiate garbage collection or finalization.See the class-level documentation for further explanation and usage examples.
- Parameters:
ref- the reference. If null, this method has no effect.
-
-