1. Unsafe releases
when sharing data between threads, there is a lack of a happens-before relationship between "Publish a shared object" and "another thread accesses the object" (such as a, b two threads, to ensure that the thread of Operation B sees the result of operation A, then A and B must meet Happens-before relationship ), a reordering problem may occur. In the absence of sufficient synchronization, publishing an object may cause another thread to see an object that is only partially constructed.
Let's start with a double check. Locking (DCL) Single-instance implementation
/** * DCL Single case * @author RENHJ * */public class Doublecheckedlocking {public static doublecheckedlocking instance;private Dou Blecheckedlocking () {}public static doublecheckedlocking getinstance () {if (instance = = null) {synchronized ( Doublecheckedlocking.class) {if (instance = = null) {instance = new doublecheckedlocking ();}}} return instance;} public static void Main (string[] args) {System.out.println (doublecheckedlocking.getinstance ()); System.out.println (Doublecheckedlocking.getinstance ());}}
Instance = new Doublecheckedlocking (); This line creates an object that is not an atomic operation and is divided into the following three steps:
1) Allocate memory//Allocate RAM to Doublecheckedlocking
2) Invoke constructor//doublecheckedlocking constructor instantiation
3) give reference//instance reference points to allocated memory address
Because the Java compiler allows the processor to execute in a random order (Out-of-order), the 2nd and 3rd orders above are not guaranteed, that is, the order of execution may be either 1-3-2, or, if the latter, the current instance reference is a partially constructed object.
This DCL implementation is very bad, first check whether the initialization is required without synchronization, if the instance reference is not empty, then use it directly. Otherwise, it synchronizes and checks if the resource is initialized, ensuring that only one thread performs initialization on the shared doublecheckedlocking. The real problem with DCL is that when a shared object is read without synchronization, the worst thing that can happen is to see an invalid value (in this case a null value), at which point the DCL method avoids this risk by trying again in the case of holding the lock. However, the reality is much worse than this, the thread may see the current value of the reference, but the state of the object is actually invalidated (in this case a partially constructed object).
In later versions of Java5.0, If instance is declared as a volatile type, the write to instance forces the modification of the cache to be immediately written to main memory. Instance in other thread caches are set to an invalid state, ensuring that the instance read in shared memory is up-to-date and satisfies the happens_before relationship.
2. Common patterns for secure publishing
Mutable objects must be published in a secure manner, to safely publish an object, the object's reference, and the state of the object must be visible to other threads at the same time, and a properly constructed object can be safely published in the following ways:
1. Initializes a reference to an object in the static initialization function.
2. Save the object's reference to a volatile type of domain or Atomicreferance object.
3. Save the object's reference to a final type field in which the object is constructed correctly.
4. Save the object's reference to a lock-protected domain.
Static initializers are performed by the JVM during the initialization phase of the class, and there is a synchronization mechanism inside the JVM, so that initializing any object in this way can be safely published, for example: public static doublecheckedlocking DCL = new doublecheckedlocking () ; volatile-modified objects have visibility, which guarantees that the modified values are immediately updated to main memory, and that when other threads need to read it, it will go to read the new value in RAM to ensure that the object is securely released , the final decorated object, then the object is immutable, can ensure that it is safe to publish, lock to ensure visibility, the object's write and read operations are locked, to ensure the safe release of objects.
Attached Happens-before partial order relationship at a glance:
1. Rules of Procedure Order: within a thread, in code order, written in front of the operation first occurs in the operation after writing
2. Locking rule: A unlock operation first occurs after the face of the same lock amount lock operation. It is important to emphasize the same lock, where the "back" is the chronological order.
3. Volatile variable rule: The write operation of a variable precedes the reading of the variable, where "back" is the order of time.
4. Thread Initiation rule: the Start () method of the thread object takes precedence over each action of this thread.
5. Thread break rule: the invocation of the thread interrupt () method first occurs when the code of the interrupted thread detects that the interrupt event occurred, and can be detected by the thread.interrupted () method.
6. Thread termination rule: All operations in a thread occur first in thread termination detection, and we can detect that the thread has terminated execution by means of the Thread.Join () method end, Thread.isalive () return value.
7. Object Finalization rule: Initialization of an object (the completion of the execution of the constructor) occurs first at the beginning of his finalize () method.
8. Delivery rules: If operation a first occurs in Operation B, and Operation B is first occurred in Operation C, you can conclude that operation a precedes operation C.
Talking about security release through the DCL single-instance implementation