Working memory vs. main memory
the Java Memory Model (JMM) appears to be a difference in memory access for various operating systems and hardware.
The Java memory model specifies that variables ( without local variables, because local variables are private, no sharing issues ) have to be stored in main memory, and each of these variables must be taken out of the main memory and done in working memory (such as reading, ), the working memory of each other cannot be accessed between different threads. For example, show the interaction between threads, main memory, and working memory:
The purpose of joining a working memory is obviously to speed up the operation of data in memory, because the working memory is first stored in registers and caches, both of which are much faster than the main memory.
The main operations for interaction between main memory and working memory are :
L Lock: A variable acting on the main memory, which marks the main memory as private to the current thread and cannot be accessed by other threads.
L Unlock(unlock): A variable acting on the main memory, releasing the lock state of the variable in main memory, and making him a thread-sharing variable.
L read: A variable that acts on the main memory and reads the variable into the working memory of the current thread for the load operation.
L Load: A variable that acts on the working memory and loads the variable read to it into a copy of the variable in the working memory.
L Use: A variable that acts on the working memory, and the virtual machine execution engine executes the byte-code instruction when it encounters a variable and uses that variable.
L assgin(Assignment): A variable that acts on the working memory, and the virtual machine execution engine executes the instruction of the variable assignment when it executes the byte code instruction.
L Store: A variable in working memory that puts a variable in the working memory into main memory for write operations.
L Write: A variable that acts on the main memory and puts the store -obtained variable into the main memory variable.
Obviously, if two threads aandB access the same variable 2 , there is no lock.
a in the working memory changed the value of the variable +1, and b at this time do not see this operation,B also thought that no one change this value, think that they are the original value on the Operation -1 . How much does the calculated value turn out to be? Oh, I don't know, because it could be 3, or maybe 1. At this point, there is a thread-safety issue with concurrent access.
VolatileVariable
Volatile is the most lightweight synchronization mechanism provided by the JVM , but it is not easy to use correctly.
Volatile can guarantee the visibility of two of threads to variable operations, that is, the operation of one thread can be seen by another. However, if the operation is not atomic, there is still no guarantee of the correctness of the volatile synchronization. You can use this keyword only in the following cases:
The write operation to the variable does not depend on the current value of the variable (for example, the a=0;a=a+1 operation , the whole process is initialized to 0, the value of a is 0 Add 1to the base and assign a value to a itself, which is obviously dependent on the current value), or to ensure that only a single thread modifies the variable.
L This variable is not included in the invariant condition with other state variables . (volatile can guarantee secure access when the variable itself is immutable, such as a singleton pattern of double judgments.) But once other state variables are mixed in, concurrency is unpredictable and correctness is not guaranteed.
Package org.project.loda.test;/** * * @ClassName: Singleton * @Description: Single-case mode based on double judgment (widely used) * @author minjun* @date 2015 Year June 5 pm 10:20:37 * */public class Singleton {private static volatile Singleton s;public static Singleton getinstance () {if (s = = null) {synchronized (Singleton.class) {if (s = = null) {s = new Singleton ();}}} return s;}}
Another feature of volatile is that he can prohibit commands from reordering optimizations. What is reordering? Take a look at the explanations in Java concurrency programming:
various operational delays or seemingly disorderly execution of different reasons can be attributed to the re-order.
This is an indirect explanation because the direct interpretation is difficult to understand. Here's a look at this app:
If you judge by the order of the top to bottom, the thread one execution order is: A=1,x=b, the thread other execution order should be: B=1,y=a. It then finishes the calculation and prints its value. However, the facts may be:
Oh, my God. X=b unexpectedly in A=1 before the execution!!! What happened? In fact, this is the bottom of the optimization of multi-threaded procedures at the time of the reordering operation, resulting in chaos. The scariest thing is that this is not necessarily the case, he may happen, it may not happen, you can't even expect it!
So, the strong point of volatile itself is that he can prevent this, although sacrificing a bit of performance, but greatly enhance the reliability of the program. But remember, don't rely on volatile, use it at the right time (explained above), and use the traditional synchronized keyword to synchronize access to shared variables if the situation is inappropriate. To ensure the correctness of the program (the performance of this keyword will continue to improve as the JVM continues to improve, future performance will slowly approximate volatile).
Happens-beforePrinciple
With so much to say, you can use the volatile and synchronized keywords to synchronize. However, you don't use them for no reason, but you should consider using them when there is a competitive, thread-safe issue, but how can you tell if there are problems? The following describes a key principle in the Java memory model-the first occurrence principle (Happens-before), which is used as a basis to guide you in determining whether there is thread safety and competition issues .
L Program Order rules: In the program, if a operation before the B operation (such as a code above the B code, or by a program called the B program), In this thread, theA operation is performed before the B operation.
L Manage locking rules: A unlock operation is performed before the lock operation that faces the same lock after it.
L volatile variable rule: A write operation on a volatile variable must occur before the read operation on the variable.
L Thread Start rule: The thread's Thread.Start must occur before all other operations on that thread
L Thread Termination rule: All operations in a thread precede the termination detection of that thread. You can determine whether a thread terminates by the return value of the Thread.Join () method end,thread.isalive () .
L Thread Break rule: The call to the thread interrupt () method must be executed before the code of the interrupted thread detects the interrupt call.
L Object Finalization rule: Initialization of an object (call to the constructor) must be done on the object's Finalize () method.
L transitivity: If a precedes b,b first occurs in C, then a precedes C.
These operations are a pre-occurrence rule that can be guaranteed without using any synchronization means.if you want to threadA,B, you needBcan seeAThe result of the operation (whether the two are in a thread) requiresA,BMeetHappens-beforerelationship, if two operations do not existHappens-beforerelationship,JVMwould arbitrarily reorder them .。 WhenAAndBIn the same thread, or two threads using the same lock, they will be able to satisfyHappens-before, if a different lock is used, it is not satisfied.
Thread
threads, also known as lightweight processes, are the basic dispatch units for most modern operating systems . In the same process, multiple threads share memory space, so sufficient synchronization mechanisms are required to ensure normal access. Each thread itself has its own program counters, stacks, and local variables. The way in which thread scheduling is used in Java is preemptive and requires the operating system to allocate execution time that the thread itself cannot decide (for example, in Java , only Thread.yield () You can make your own execution time, but do not provide an action that can proactively get execution time. Although the Java thread Scheduler is executed by the system, it is still possible to "recommend" the operating system to assign execution time to certain threads by setting the priority of the threads (then, this does not necessarily guarantee high-priority execution first, so it is not very reliable ...) )。
Java defines the following types of thread states, one with only one thread:
Specifying several states and the processes that are required to achieve them are not explained here, and the basic students should be able to read them easily.
references:java concurrency Programming combat
deep Java Virtual machines (JVM advanced features and best practices )
Java Memory models and threads