@Documented @Retention(value=RUNTIME) @Target(value=TYPE) public @interface ThreadSafe
RegionLock models has been developed to document the
locking policy of a class this annotation can help to clarify that the
overall class is thread-safe.
This annotation does not imply that a sequence made up of calls to methods of this class or accesses to fields of this class are atomic. It is a the responsibility of the caller to insure that such sequences execute atomically.
This annotation is currently verified, but not defined, by
restricting how the fields of the class are declared and annotated. This is a
conservative, although easily understood, way to verify the
ThreadSafe assertion. Specifically, for a class annotated as
@ThreadSafe to be verified, each field must be either
final and be "safe,"
volatile and be "safe," or
@RegionLock annotation) and be "safe."
@ThreadSafe.
@Immutable.
@Containable and the
field is either
@Unique and the Instance region
is protected by a lock.
@UniqueInRegion such that each destination
region is protected by a lock.
A field with an array type is considered containable if the array is 1-dimensional and the base type of the array is a primitive type.
Some implementations may not be "safe" as defined above, but still
thread-safe. Such practices may or may not be verifiable by a tool, such as
SureLogic JSure. Use of the Vouch annotation can be used, especially
annotation of @Vouch("ThreadSafe") or
@Vouch("Immutable") on a field, to suppress overly
conservative tool results.
Immutable objects are inherently thread-safe; they may be passed
between threads or published without synchronization. Therefore instances of
an Immutable type are also ThreadSafe, but not necessarily
vice versa.
Typically, subtypes of the annotated type must be explicitly annotated
@ThreadSafe or (the more restrictive, but also thread-safe)
@Immutable. It is a modeling error if they are not. This
annotation has two attributes, implementationOnly and
verify, that control how subtypes of an ThreadSafe type must
be annotated. The implementationOnly attribute indicates that the
implementation of the annotated class should be assured without making a
general statement about the visible behavior of the type or its subtypes.
There are several rules with regards to the implementationOnly
attribute on ThreadSafe types:
false when
ThreadSafe appears on an interface, because interfaces do not have an
implementation.ThreadSafe must
be annotated with ThreadSafe; classes that implement an interface
annotated with ThreadSafe must be annotated with
@ThreadSafe(implementationOnly=false).ThreadSafe, but that is not verifiable using the syntactic and
annotation constraints described above. For this case, we provide the
"escape hatch" of turning off tool verification for the annotation with the
verify attribute. For example,
@ThreadSafe(verify=false) would skip tool verification
entirely.
A type may not be annotated with both @ThreadSafe and
@NotThreadSafe.
An annotation type declaration may be annotated with @ThreadSafe
so that any static fields in the type are verified as thread-safe.
By default the static part of a class implementation is checked that it is thread-safe as well as the instance part. It is possible to specify which portions of the class implementation are checked using the appliesTo attribute. This value can be one of
@ImmutableThread safety and immutability are two points along the same axis. This set of annotations can actually describe three points along the axis:
@Mutable and @NotThreadSafe
@Mutable
, or just @NotThreadSafe. The type contains mutable state
that is not safe to access concurrently from multiple threads.
@Mutable and @ThreadSafe
@ThreadSafe. The type contains
mutable state that is safe to access concurrently from multiple threads.
@Immutable and @ThreadSafe
@Immutable. The type contains no
mutable state, and is thus safe to access concurrently from multiple threads.
The combination @Immutable and
@NotThreadSafe is a modeling error because an immutable
type is obviously thread safe.
An @Immutable interface may extend a
@ThreadSafe interface. An @Immutable
class may implement a @ThreadSafe interface.
A @ThreadSafe class may extend a class annotated with
@Immutable(implementationOnly=true).
final, non-volatile region of
an instance of the annotated class occur either when
Point class is thread-safe because its fields are
final and of primitive type.
@ThreadSafe
@Containable
public class Point {
private final int x;
private final int y;
@Unique("return")
@RegionEffects("none")
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Borrowed("this")
@RegionEffects("none")
@Unique("return")
public Point translate(int dx, int dy) {
return new Point(x + dx, y + dy);
}
}
The Rectangle class is thread-safe because its fields are
final and of a type annotated @ThreadSafe:
@ThreadSafe
@Containable
public class Rectangle {
@Unique
private final Point topLeft;
@Unique
private final Point bottomRight;
@Unique("return")
@RegionEffects("none")
public Rectangle(@Unique Point a, @Unique Point b) {
topLeft = a;
bottomRight = b;
}
@Borrowed("this")
@RegionEffects("none")
@Unique("return")
public Rectangle translate(int dx, int dy) {
return new Rectangle(topLeft.translate(dx, dy), bottomRight.translate(dx, dy));
}
}
Alternatively, we can create a mutable thread-safe Rectangle
class by protecting the state with a lock, and aggregating a containable
mutable, but not thread-safe, Point class:
@Containable
public class Point {
private int x;
private int y;
@Unique("return")
@RegionEffects("none")
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Borrowed("this")
@RegionEffects("writes Instance")
public void translate(int dx, int dy) {
x += dx;
y += dy;
}
}
@ThreadSafe
@RegionLock("Lock is this protects Instance")
public class Rectangle {
@Unique
private final Point topLeft;
@Unique
private final Point bottomRight;
@Unique("return")
public Rectangle(int x1, int y1, int x2, int y2) {
topLeft = new Point(x1, y1);
bottomRight = new Point(x2, y2);
}
@Borrowed("this")
@RegionEffects("writes Instance")
public synchronized void translate(int dx, int dy) {
topLeft.translate(dx, dy);
bottomRight.translate(dx, dy);
}
}
A @Vouch("ThreadSafe") annotation is used to vouch
that a private array is thread safe after object construction. Because the
Java language does not allow the programmer to express that the contents of
the array are thread-safe, use of a Vouch is necessary in this
example.
@ThreadSafe
public class Aircraft {
@Vouch("ThreadSafe")
private final Wing[] f_wings;
@Unique("return")
@RegionEffects("none")
public Aircraft() {
f_wings = new Wing[2];
f_wings[0] = new Wing();
f_wings[1] = new Wing();
}
...
}
One area where the @Vouch("ThreadSafe") annotation
(or the more restrictive @Vouch("Immutable")
annotation) is often needed is when collections are used within an immutable
class. The code below shows an example where a collection is vouched for.
@ThreadSafe
public final class MutableEntityMgr {
@Vouch("Immutable")
private final Map<String, String> f_defaults;
@Vouch("ThreadSafe")
private final Map<String, String> f_additions;
public MutableEntityMgr() {
Map<String, String> known = new HashMap<String, String>();
// add defaults
known.put("<", "<");
known.put(">", ">");
f_defaults = Collections.unmodifiableMap(known);
f_additions = Collections.synchronizedMap(new HashMap<String, String>());
}
public String convertIfRecognized(String entity) {
String value = f_additions.get(entity);
if (value == null)
value = f_defaults.get(entity);
return value == null ? entity : value;
}
}
As an example of treating the static and instance state of a class
differently, consider the Point class below. The instances of
the class are considered immutable, but the static state is mutable
and thread-safe. This is because the static state is used to maintain a
cache of instantiated points.
@Immutable(appliesTo=Part.Instance)
@ThreadSafe(appliesTo=Part.Static)
@Region("private static Points")
@RegionLock("PointsLock is points protects Points")
public final class Point {
@UniqueInRegion("Points")
private final static List<Point> points = new ArrayList<Point>();
private final int x;
private final int y;
private Point(final int x, final int y) {
this.x = x;
this.y = y;
}
public boolean equals(final int x, final int y) {
return this.x == x && this.y == y;
}
public static Point getPoint(final int x, final int y) {
synchronized (points) {
for (final Point p : points) {
if (p.equals(x, y)) return p;
}
final Point p = new Point(x, y);
points.add(p);
return p;
}
}
// ...
}
@annotate tag.
/**
* @annotate ThreadSafe
* @annotate RegionLock("Lock is this protects Instance")
*/
public class Rectangle {
...
}
Implementation note: This annotation is derived from
@ThreadSafe 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. One difference between the two annotations is that the
annotation in com.surelogic adds the implementationOnly and
verify attributes—these attributes can not be changed from
their default values if the the net.jcip.annotations annotation is
used.AnnotationBounds,
Containable,
Immutable,
NotThreadSafe,
Part,
Region,
RegionLock,
Vouch| Modifier and Type | Optional Element and Description |
|---|---|
Part |
appliesTo
Indicates whether the instance state of the class, static state of the
class, or both are subject to verification.
|
boolean |
implementationOnly
Indicates that the implementation of the annotated class should be assured
without making a general statement about the visible behavior of the type
or its subtypes.
|
boolean |
verify
Indicates whether or not tool verification should be attempted.
|
public abstract boolean implementationOnly
true if only the annotated class should be assured without
making a general statement about the visible behavior of the type
or its subtypes, false otherwise. The default value for
this attribute is false.public abstract boolean verify
true if the claim should be verified by a tool, such as
SureLogic JSure, false otherwise. The default value for
this attribute is true.public abstract Part appliesTo
Copyright © 2012 Surelogic, Inc.. All Rights Reserved.