Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Changed to JG and fixed a link

The Java language annotation facility is useful for documenting design intent. Source code annotation is a mechanism for associating metadata with a program element and making it available to the compiler, analyzers, debuggers, or the Java Virtual Machine (JVM) for examination. Several annotations are available for documenting thread-safety or the lack thereof.

Obtaining Concurrency Annotations

Two sets of concurrency annotations are freely available and licensed for use in any code. The first set consists of four annotations described in Java Concurrency in Practice (JCIP) [Goetz 2006], which can be downloaded from jcip.net (jar, javadoc, source). The JCIP annotations are released under the Creative Commons Attribution License.

...

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 sections.

Documenting Intended Thread-Safety

JCIP provides three class-level annotations to describe the programmer's design intent with respect to thread-safety.

...

For example, the following Aircraft class specifies that it is thread-safe as part of its locking policy documentation. This class protects the x and y fields using a reentrant lock.

Code Block
bgColor#ccccff

 @ThreadSafe
 @Region("private AircraftState")
 @RegionLock("StateLock is stateLock protects AircraftState")
 public final class Aircraft {
   private final Lock stateLock = new ReentrantLock();
   // ...
   @InRegion("AircraftState")
   private long x, y;
   // ...
   public void setPosition(long x, long y) {
     stateLock.lock();
     try {
       this.x = x;
       this.y = y;
     } finally {
       stateLock.unlock();
     }
   }
   // ...
 }

...

The following example shows an immutable Point class:

Code Block
bgColor#ccccff

 @Immutable
 public final class Point {
   private final int f_x;
   private final int f_y;

   public Point(int x, int y) {
     f_x = x;
     f_y = y;
   }

   public int getX() {
     return f_x;
   }

   public int getY() {
     return f_y;
   }
 }

...

For example, most of the collection implementations provided in java.util are not thread-safe. The class java.util.ArrayList could document this as follows:

Code Block
bgColor#ccccff

 package java.util.ArrayList;

 @NotThreadSafe
 public class ArrayList<E> extends ... {
   // ...
 }

Documenting Locking Policies

It is important to document all the locks that are being used to protect shared state. According to Goetz and colleagues [Goetz 2006, p. 28],

...

For example, the following MovablePoint class implements a movable point that can remember its past locations using the memo array list.

Code Block
bgColor#ccccff

@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);
    }
  }
}

...

For example, the SimpleLock locking policy indicates that synchronizing on the instance protects all of its state:

Code Block
bgColor#ccccff

 @RegionLock("SimpleLock is this protects Instance")
 class Simple { ... }

...

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:

Code Block
bgColor#ccccff

 @Region("private AircraftPosition")
 @RegionLock("StateLock is stateLock protects AircraftPosition")
 public final class Aircraft {
   private final Lock stateLock = new ReentrantLock();

   @InRegion("AircraftPosition")
   private long x, y;

   @InRegion("AircraftPosition")
   private long altitude;
   // ...
   public void setPosition(long x, long y) {
     stateLock.lock();
     try {
       this.x = x;
       this.y = y;
     } finally {
       stateLock.unlock();
     }
   }
   // ...
 }

In this example, a locking policy named StateLock is used to indicate that locking on stateLock protects the named AircraftPosition region, which includes the mutable state used to represent the position of the aircraft.

Construction of Mutable Objects

Typically, object construction is considered an exception to the locking policy because objects are thread-confined when they are created. An object is confined to the thread that uses the new operator to create its instance. After creation, the object can be published to other threads safely. However, the object is not shared until the thread that created the instance allows it to be shared. Safe publication approaches discussed in rule rule TSM01-J. Do not let the this reference escape during object construction can be expressed succinctly with the @Unique("return") annotation.

For example, in the following code, the @Unique("return")annotation documents that the object returned from the constructor is a unique reference.

Code Block
bgColor#ccccff

 @RegionLock("Lock is this protects Instance")
 public final class Example {
   private int x = 1;
   private int y;

   @Unique("return")
   public Example(int y) {
     this.y = y;
   }
   // ...
 }

Documenting Thread-Confinement Policies

Sutherland and Scherlis propose annotations that can document thread-confinement policies. Their approach allows verification of the annotations against as-written code [Sutherland 2010].

For example, the following annotations express the design intent that a program has, at most, one AWT event dispatch thread and several compute threads, and that the compute threads are forbidden to handle AWT data structures or events:

Code Block
bgColor#ccccff

@ThreadRole AWT, Compute
@IncompatibleThreadRoles AWT, Compute
@MaxRoleCount AWT 1

Documenting Wait-Notify Protocols

According to Goetz and colleagues [Goetz 2006, p. 395],

...

Wait-notify protocols should be documented adequately. Currently, we are not aware of any annotations for this purpose.

Risk Assessment

Annotating concurrent code documents design intent and can be used to automate the detection and prevention of race conditions and data races.

Rule Guideline

Severity

Likelihood

Remediation Cost

Priority

Level

TSM04CON52-J JG

low

probable

medium

P4

L3

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Bibliography

[Bloch 2008]

Item 70: "Document thread safety"

[Goetz 2006]

 

[Sutherland 2010]

 

 

      11. Thread-Safety Miscellaneous (TSM)      12. Input Output (FIO)