logo

Quotes from Brian Goetz

Yet accessing a volatile variable performs no locking and so cannot cause the executing thread to block, making volatile variables a lighter-weight synchronization mechanism than synchronized.[5]
~ Brian Goetz
However, we do not recommend relying too heavily on volatile variables for visibility; code that relies on volatile variables for visibility of arbitrary state is more fragile and harder to understand than code that uses locking.
~ Brian Goetz
You can use volatile variables only when all the following criteria are met: Writes to the variable do not depend on its current value, or you can ensure that only a single thread ever updates the value; The variable does not participate in invariants with other state variables; and Locking is not required for any other reason while the variable is being accessed.
~ Brian Goetz
Do not allow the this reference to escape during construction.
~ Brian Goetz
A special case of thread confinement applies to volatile variables. It is safe to perform read-modify-write operations on shared volatile variables as long as you ensure that the volatile variable is only written from a single thread. In this case, you are confining the modification to a single thread to prevent race conditions, and the visibility guarantees for volatile variables ensure that other threads see the most up-to-date value. Because
~ Brian Goetz
If multiple threads access the same mutable state variable without appropriate synchronization, your program is broken. There are three ways to fix it: Don't share the state variable across threads; Make the state variable immutable; or Use synchronization whenever accessing the state variable.
~ Brian Goetz
If you haven't considered concurrent access in your class design, some of these approaches can require significant design modifications, so fixing the problem might not be as trivial as this advice makes it sound. It is far easier to design a class to be thread-safe than to retrofit it for thread safety later. In
~ Brian Goetz
When designing thread-safe classes, good object-oriented techniques—encapsulation, immutability, and clear specification of invariants—are your best friends.
~ Brian Goetz
There will be times when good object-oriented design techniques are at odds with real-world requirements; it may be necessary in these cases to compromise the rules of good design for the sake of performance or for the sake of backward compatibility with legacy code. Sometimes abstraction and encapsulation are at odds with performance—although not nearly as often as many developers believe—but it is always a good practice first to make your code right, and then make it fast.
~ Brian Goetz
A class is thread-safe if it behaves correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code.
~ Brian Goetz
Stateless objects are always thread-safe.
~ Brian Goetz
Publishing an object also publishes any objects referred to by its nonprivate fields. More generally, any object that is reachable from a published object by following some chain of nonprivate field references and method calls has also been published. From
~ Brian Goetz
A race condition occurs when the correctness of a computation depends on the relative timing or interleaving of multiple threads by the runtime; in other words, when getting the right answer relies on lucky timing.
~ Brian Goetz
The most common type of race condition is check-then-act, where a potentially stale observation is used to make a decision on what to do next. [4]
~ Brian Goetz
If you are tempted to register an event listener or start a thread from a constructor, you can avoid the improper construction by using a private constructor and a public factory method, as shown in SafeListener in Listing 3.8. Listing
~ Brian Goetz
Because of its fragility, ad-hoc thread confinement should be used sparingly; if possible, use one of the stronger forms of thread confinment (stack confinement or ThreadLocal) instead. 3.3.2.
~ Brian Goetz
A synchronized block has two parts: a reference to an object that will serve as the lock, and a block of code to be guarded by that lock.
~ Brian Goetz
Static synchronized methods use the Class object for the lock.)
~ Brian Goetz
you can think of a ThreadLocal as holding a Map that stores the thread-specific values, though this is not how it is actually implemented. The thread-specific values are stored in the Thread object itself; when the thread terminates, the thread-specific values can be garbage collected. If
~ Brian Goetz
When a thread requests a lock that is already held by another thread, the requesting thread blocks. But because intrinsic locks are reentrant, if a thread tries to acquire a lock that it already holds, the request succeeds. Reentrancy means that locks are acquired on a per-thread rather than per-invocation basis.
~ Brian Goetz
The other end-run around the need to synchronize is to use immutable objects [EJ Item 13]. Nearly all the atomicity and visibility hazards we've described so far, such as seeing stale values, losing updates, or observing an object to be in an inconsistent state, have to do with the vagaries of multiple threads trying to access the same mutable state at the same time. If an object's state cannot be modified, these risks and complexities simply go away. An
~ Brian Goetz
An immutable object is one whose state cannot be changed after construction. Immutable objects are inherently thread-safe; their invariants are established by the constructor, and if their state cannot be changed, these invariants always hold.
~ Brian Goetz
Immutable objects are always thread-safe.
~ Brian Goetz