@Documented @Retention(value=RUNTIME) @Target(value={FIELD,METHOD}) public @interface GuardedBy
The argument determines which lock guards the annotated field or method:
this: The intrinsic lock of the object in whose class the field
is defined.class-name.this: For inner classes, it may be necessary to
disambiguate 'this'; the class-name.this designation allows you to
specify which 'this' reference is intendeditself: For reference fields only; the object to which the field
refers.field-name: The lock object is referenced by the (instance or
static) field specified by field-name.class-name.field-name: The lock object is reference by the
static field specified by class-name.field-name.method-name(): The lock object is returned by calling the named
nil-ary method.class-name.class: The Class object for the specified class
should be used as the lock object.Method: The program must be holding the specified lock when the annotated method is invoked.
Point class below is considered thread-safe.
@ThreadSafe
public class ex1 {
@GuardedBy("this")
double xPos = 1.0;
@GuardedBy("this")
double yPos = 1.0;
@GuardedBy("itself")
static final List<ex1> memo = new ArrayList<ex1>();
public void move(double slope, double distance) {
synchronized (this) {
xPos = xPos + ((1 / slope) * distance);
yPos = yPos + (slope * distance);
}
}
public static void memo(ex1 value) {
synchronized (memo) {
memo.add(value);
}
}
}
The example below shows how the generated lock name may be referenced in a
RequiresLock annotation:
public class Var {
@GuardedBy("this")
private int value;
public synchronized void set(final int v) {
value = v;
}
@RequiresLock("Guard$_value")
public int get() {
return value;
}
}
Constructor annotation to support locking policies: To support the
GuardedBy annotation, a Unique or Borrowed annotation
is needed on each constructor to assure that the object being constructed is
confined to the thread that invoked new. A second less common
approach, using effects, is described below.
Annotating @Unique("return") on a constructor is defined to
be equivalent to annotating @Borrowed("this"). Either of
these annotations indicate that the object being constructed is not aliased
during construction, which implies that the reference "returned" by the
new expression that invokes the constructor is unique. Which
annotation is preferred, @Unique("return") or
@Borrowed("this"), is a matter of programmer preference.
public class Example {
@GuardedBy("this") int y;
@Unique("return")
public Example(int y) {
this.y = y;
}
...
}
It is also possible to support the GuardedBy assertion with effects (
Starts and RegionEffects) annotations on a constructor
instead of using Unique or Borrowed. This is useful if the
constructor aliases the receiver into a field within the newly constructed
object. This situation is uncommon in real-world Java code. In the example
below if an explicit lock object is not provided to the constructor then
this is used and, hence, aliased into the field lock. In this
code @Unique("return") cannot be verified so the effects
annotations are used on the constructor instead.
public class Example {
private final Object lock;
@GuardedBy("lock")
private int y;
@Starts("nothing")
@RegionEffects("none")
public Example(int y, Object lock) {
this.y = y;
if (lock == null)
this.lock = this;
else
this.lock = lock;
}
public int getY() {
synchronized (lock) {
return y;
}
}
public void setY(int value) {
synchronized (lock) {
y = value;
}
}
}
The scoped promise Promise can be used if the constructor is implicit
(i.e., generated by the compiler). It has the ability to place promises on
implicit and explicit constructors.
@Promise("@Unique(return) for new(**)")
public class Example {
@GuardedBy("this") int x = 1;
@GuardedBy("this") int y = 1;
...
}
@annotate tag.
/**
* @annotate GuardedBy("this")
*/
double xPos = 1.0;
Implementation note: This annotation is derived from
@GuardedBy proposed by Brian Goetz and Tim Peierls in the
book Java Concurrency in Practice (Addison-Wesley 2006) we have simply
adapted it to have semantics as a promise. Further, the annotation in
net.jcip.annotations may be used instead of this one with the same
tool behavior.
The SureLogic JSure tool supports verification of all the above forms except
for itself and method-name(). The other forms are
supported by translating this annotation into a RegionLock annotation
on the class that contains the annotated field. A lock name is generated to
use with RegionLock annotation: for a GuardedBy annotation on
a field f we generate the lock name Guard$_f, where
$ is meant to be pronounced as an S. The supported cases
are translated as follows:
@GuardedBy("this") on field f in
class C generates a @RegionLock("Guard$_f is this
protects f") on class C.
@GuardedBy("class-name.this") on field
f in class C generates a
@RegionLock("Guard$_f is class-name.this protects f") on
class C.
@GuardedBy("field-name") on field f
in class C generates a @RegionLock("Guard$_f is
field-name protects f") on class C.
@GuardedBy("class-name.field-name") on field
f in class C generates a
@RegionLock("Guard$_f is class-name.field-name") on class
C.
@GuardedBy("class-name.class") on field
f in class C generates a
@RegionLock("Guard$_f is class-name.class") on class
C.
RegionLock,
ThreadSafe| Modifier and Type | Required Element and Description |
|---|---|
String |
value
The value of this attribute must conform to the following grammar (in Augmented Backus–Naur
Form):
|
public abstract String value
The value of this attribute must conform to the following grammar (in Augmented Backus–Naur Form):
value = "this" / "itself" / class / field / method
class = qualifiedName "." ("class" / "this")
field = qualfiedName
method = qualifiedName "()"
qualifiedName = IDENTIFIER *("." IDENTIFIER) : IDENTIFIER
IDENTIFIER = Legal Java Identifier
Copyright © 2012 Surelogic, Inc.. All Rights Reserved.