Javadoc comments should describe how the responsibilities for ensuring correct multi-threaded behaviour are shared between a class and its caller. This is equivalent to stating the circumstances, if any, in which the caller must explicitly obtain an external lock before performing certain operations. The central questions to be answered by the documentation are:
"When do these objects require external synchronization?"
"Which lock is needed for which operations?"
Here, "operations" on an object might come in two flavours:
- single-call operations, where only a single method is called
- multiple-call operations, where more than one method is called, and they are treated as a single unit; the classic example is iteration over a collection
- it focuses more on the point of view of the caller, instead of class internals
- the language is simpler and clearer
The goal of this scheme is simply to tell the caller when they need to obtain an external lock before performing an operation in a multithreaded environment.
lock-never - the caller never needs to obtain an external lock before performing any operation of any kind. The class may be immutable, or it may perform all necessary synchronization internally. From the point of view of the caller, these two cases are functionally the same (in the context of documenting thread-safety).
lock-always - the caller always needs to obtain an external lock before performing any operation. Instances are mutable, and the implementation of the class performs no internal synchronization.
lock-sometimes - the caller sometimes needs to obtain a lock externally before performing some operations. Instances are mutable, and the implementation of the class performs most synchronization internally. The caller usually doesn't need to obtain an external lock, but there are some operations in which the caller does indeed need to obtain an external lock. The classic example of this is iteration over a collection.
lock-hostile - operations cannot be performed safely in a multi-threaded environment at all, even when an external lock is always obtained. This is a rare pathological case. It usually occurs when static data is modified without proper synchronization.
In practice, lock-always and lock-never are likely the most common cases.
To help you with documenting thread-safety, you might consider using:
- annotations, for example those defined by Brian Goetz
- javadoc's -tag option, which lets you define simple custom javadoc tags
Another reasonable option is to state in the javadoc overview that, unless stated otherwise, a class is to be considered lock-always.