...
To use the annotations, download and add one or both of the aforementioned JAR files to the code's build path. The use of these annotations to document thread-safety is described in the following sectionsdescr
Warning | ||
---|---|---|
| ||
These examples are based on SureLogic, as of 2010. The intent is still useful but the implementation is no longer supported. We recommend using an annotation package that still enjoys active support. |
Documenting Intended Thread-Safety
...
The @Region
and @RegionLock
annotations document the locking policy upon which the promise of thread-safety is predicated.
Even when one or more @RegionLock
or @GuardedBy
annotations have been used to document the locking policy of a class, the @ThreadSafe
annotation provides an intuitive way for reviewers to learn that the class is thread-safe.
...
For each mutable state variable that may be accessed by more than one thread, all accesses to that variable must be performed with the same lock held. In this case, we say that the variable is guarded by that lock. (p. 28)
JCIP provides the @GuardedBy
annotation for this purpose, and SureLogic provides the @RegionLock
annotation. The field or method to which the @GuardedBy
annotation is applied can be accessed only when holding a particular lock. It may be an intrinsic lock or a dynamic lock such as java.util.concurrent.Lock
.
...
Code Block | ||
---|---|---|
| ||
@ThreadSafe public final class MovablePoint { @GuardedBy("this") double xPos = 1.0; @GuardedBy("this") double yPos = 1.0; @GuardedBy("itself") static final List<MovablePoint> memo = new ArrayList<MovablePoint>(); public void move(double slope, double distance) { synchronized (this) { rememberPoint(this); xPos += (1 / slope) * distance; yPos += slope * distance; } } public static void rememberPoint(MovablePoint value) { synchronized (memo) { memo.add(value); } } } |
The @GuardedBy
annotations on the xPos
and yPos
fields indicate that access to these fields is protected by holding a lock on this
. The move()
method also synchronizes on this
, which modifies these fields. The @GuardedBy
annotation on the memo
list indicates that a lock on the ArrayList
object protects its contents. The rememberPoint()
method also synchronizes on the memo
list.
One issue with the @GuardedBy
annotation is that it fails to indicate when there is a relationship between the fields of a class. This limitation can be overcome by using the SureLogic @RegionLock
annotation, which declares a new region lock for the class to which this annotation is applied. This declaration creates a new named lock that associates a particular lock object with a region of the class. The region may be accessed only when the lock is held. For example, the SimpleLock
locking policy indicates that synchronizing on the instance protects all of its state:
Code Block | ||
---|---|---|
| ||
@RegionLock("SimpleLock is this protects Instance") class Simple { ... } |
Unlike @GuardedBy
, the @RegionLock
annotation allows the programmer to give an explicit, and hopefully meaningful, name to the locking policy.
In addition to naming the locking policy, the @Region
annotation allows a name to be given to the region of the state that is being protected. That name makes it clear that the state and locking policy belong together, as demonstrated in the following example:
...
For example, in the following code, the @Unique("return")
annotation documents that the object returned from the constructor is a unique reference:
...