[关闭]
@HUST-SuWB 2018-10-12T10:09:05.000000Z 字数 5964 阅读 343

《Java Concurrency in Practice》读书笔记

Finlabtech


  1. If multiple threads access the same mutable state variable without appropriate synchronization, your program is broken. There are three ways to fix it:
  2. Dont share the state variable across threads;
  3. Make the state variable immutable;
  4. Use synchronization whenever accessing the state variable.
  1. Stateless objects are always thread-safe.
  1. The Starbucks example illustrates a race condition because reaching the de- sired outcome (meeting your friend) depends on the relative timing of events (when each of you arrives at one Starbucks or the other, how long you wait there before switching, etc). The observation that he is not at Starbucks A be- comes potentially invalid as soon as you walk out the front door; he could have come in through the back door and you wouldnt know. It is this invalidation of observations that characterizes most race conditionsusing a potentially stale observation to make a decision or perform a computation. This type of race condition is called check-then-act: you observe something to be true (file X doesnt exist) and then take action based on that observation (create X); but in fact the observation could have become invalid between the time you observed it and the time you acted on it (someone else created X in the meantime), causing a problem (unexpected exception, overwritten data, file corruption).
  1. To ensure thread safety, check-then-act operations (like lazy initialization) and read-modify-write operations (like increment) must always be atomic.
  1. Every Java object can implicitly act as a lock for purposes of synchronization; these built-in locks are called intrinsic locks or monitor locks.
  1. 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.
  1. A common locking convention is to encapsulate all mutable state within an object and to protect it from concurrent access by synchronizing any code path that accesses mutable state using the objects intrinsic lock. This pattern is used by many thread-safe classes, such as Vector and other synchronized collection classes. In such cases, all the variables in an objects state are guarded by the objects intrinsic lock.
  1. There is frequently a tension between simplicity and performance. When implementing a synchronization policy, resist the temptation to prematurely sacrifice simplicity (potentially compromising safety) for the sake of performance.
  1. There is no guarantee that operations in one thread will be performed in the order given by the pro- gram, as long as the reordering is not detectable from within that threadeven if the reordering is apparent to other threads.
  1. Out-of-thin-air safety applies to all variables, with one exception: 64-bit numeric variables (double and long) that are not declared volatile (see Section 3.1.4). The Java Memory Model requires fetch and store operations to be atomic, but for nonvolatile long and double variables, the JVM is permitted to treat a 64-bit read or write as two separate 32-bit operations. If the reads and writes occur in different threads, it is therefore possible to read a nonvolatile long and get back the high 32 bits of one value and the low 32 bits of another.3 Thus, even if you dont care about stale values, it is not safe to use shared mutable long and double variables in multithreaded programs unless they are declared volatile or guarded by a lock.
  1. Volatile variables are not cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always returns the most recent write by any thread.
  1. You can use volatile variables only when all the following criteria are met:
  2. Writes to the variable do not depend on its current value, or you can ensure that only a single thread ever updates the value;
  3. The variable does not participate in invariants with other state variables;
  4. Locking is not required for any other reason while the variable is being accessed.
  1. Publishing an object also publishes any objects referred to by its non-private fields. More generally, any object that is reachable from a published object by following some chain of non-private field references and method calls has also been published.
  1. Accessing shared, mutable data requires using synchronization; one way to avoid this requirement is to not share. If data is only accessed from a single thread, no synchronization is needed. This technique, thread confinement, is one of the simplest ways to achieve thread safety. When an object is confined to a thread, such usage is automatically thread-safe even if the confined object itself is not [CPJ 2.3.2].
  1. https://blog.csdn.net/manicpixies/article/details/43238729
  1. Immutable objects are always thread-safe.
  1. There are advantages to using a private lock object instead of an objects intrinsic lock (or any other publicly accessible lock). Making the lock object private encapsulates the lock so that client code cannot acquire it, whereas a publicly accessible lock allows client code to participate in its synchronization policy correctly or incorrectly. Clients that improperly acquire another objects lock could cause liveness problems, and verifying that a publicly accessible lock is properly used requires examining the entire program rather than a single class.
  1. If a class is composed of multiple independent thread-safe state variables and has no operations that have any invalid state transitions, then it can delegate thread safety to the underlying state variables.
  1. Extension is more fragile than adding code directly to a class, because the implementation of the synchronization policy is now distributed over multiple, separately maintained source files. If the underlying class were to change its synchronization policy by choosing a different lock to guard its state variables, the subclass would subtly and silently break, because it no longer used the right lock to control concurrent access to the base classs state.
  1. Crafting a synchronization policy requires a number of decisions: which variables to make volatile, which variables to guard with locks, which lock(s) guard which variables, which variables to make immutable or confine to a thread, which operations must be atomic, etc.
  1. Iteration is also indirectly invoked by the collections hashCode and equals methods, which may be called if the collection is used as an element or key of another collection. Similarly, the containsAll, removeAll, and retainAll methods, as well as the constructors that take collections as arguments, also iterate the collection. All of these indirect uses of iteration can cause ConcurrentModificationException.
  1. Just as ConcurrentHashMap is a concurrent replacement for a synchronized hash-based Map, Java 6 adds ConcurrentSkipListMap and ConcurrentSkipList-Set, which are concurrent replacements for a synchronized SortedMap or SortedSet (such as TreeMap or TreeSet wrapped with synchronizedMap).
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注