One 、 Why there is a memory model
In modern multicore processors , Each processor has its own cache , Need regular coordination with main memory .
Want to make sure that each processor knows what other processors are doing at any time , It will cost a lot of money , And it's usually unnecessary .
1.1 Efficiency and consistency of hardware
1、 Because there are several orders of magnitude gap between the computer's storage device and the processor's computing power , So modern computer systems have to add a layer of read-write speed as close as possible to the processor speed of the cache （cache） As a buffer between memory and processor ： Copies the data that the operation needs to use into the cache , Let's make it fast , When the operation is finished, it is synchronized back into memory from the cache so that the processor does not have to wait for slow memory reads and writes .
2、 Multiple processor operations involve the same main memory , We need a protocol to guarantee the consistency of data , Such agreements are MSI、MESI、MOSI And Dragon Protocol etc. .Java The memory access operations defined in the memory model of virtual machine are comparable to the cache access operations of hardware .
3、 Cache based storage interaction solves the speed conflict between processor and memory , But a new problem has been introduced ： Cache consistency （Cache Coherence）. In a multiprocessor system , Each processor has its own cache , And they share the same main memory , I'll talk about it next
Two 、CPU And cache consistency
2.1 Why CPU cache
because CPU The frequency is too fast , It's too fast to keep up with the main memory , So in the processor clock cycle ,CPU You often have to wait for main memory , Waste resources .CPU It is often necessary to process the same data repeatedly 、 Repeat the same instruction , If this part of the data 、 Instructions CPU Can be in CPU Found in cache ,CPU There is no need to read data from memory or hard disk 、 Instructions , Thus, the response time of the whole machine is reduced , therefore cache Appearance , It's to relieve CPU Speed mismatch with memory ( structure ：cpu -> cache -> memory)
In the process of program execution, it becomes ：
When the program is running , Will copy the data needed for the operation from main memory to CPU In the cache , that CPU When calculating
You can read and write data directly from its cache , When the operation is over , Then refresh the data in the cache
Into main memory .
stay Intel Products on the official website - The definition of cache in the processor interface is ：CPU Cache is a fast memory area on the processor . Intel intelligent cache （SmartCache） Architecture that allows all kernels to dynamically share the last level of cache . This brings us to the concept of the last level of cache , That is to say CPU In the cache L3( Three level cache ), So let's go on to explain what level 3 caching is , Which three levels of cache do they refer to .
2.2 Three level cache （L1、L2、L3）
1) Three level cache （L1 First level cache 、L2 Second level cache 、L3 Three level cache ） It's all integrated in CPU Cache within 2) They all serve as CPU High speed data buffer between and main memory 3) L1 Closest to CPU The core ,L2 secondly ,L3 Again In terms of running speed ：L1 The fastest 、L2 Sub fast 、L3 The slowest
In terms of capacity ：L1 Minimum 、L2 more 、L3 Maximum
4) CPU It's going to be the fastest L1 Looking for the data you need , I can't find another fast one L2, If you can't find it, you can find it again L3,L3 If not, you can only go to the memory to find .
5) Single core CPU Only one set L1,L2,L3 cache ; If CPU Multiple cores , I.e. multi-core CPU, Each core contains a set of L1（ Even with L2） cache , And share L3（ Or and L2） cache .
single CPU Dual core cache structure ： In a single threaded environment ,cpu The core cache is accessed by only one thread . Cache exclusive , There will be no problems such as access conflicts In a multithreaded scenario , stay CPU Add cache between and main memory , There could be Cache consistency issues , in other words , In multicore CPU in , Each core's own cache , The cache contents of the same data may be inconsistent , This is what we mentioned above Cache consistency issues
2.3 Out of order optimization
from java Source code to the actual execution of the final sequence of instructions , Will experience the following 3 Species reordering ： The phenomenon of reordering ：
a=10,b=a This group b rely on a, It doesn't reorder
a=10,b=50 This group a and b It doesn't matter. , Then it can be reordered b=50,a=10
cpu And compiler will allow instruction optimization according to certain rules in order to improve the efficiency of program execution , Does not affect the results of single threaded program execution , But multithreading will affect the results of the program
3、 ... and 、java Memory model
Java The memory model is Java Memory Model, abbreviation JMM.JMM Defined Java virtual machine (JVM) In the computer memory (RAM) How to work in .JVM It's the whole computer virtual model , therefore JMM It belongs to JVM Of .
Java Memory model （Java Memory Model ,JMM） It's a memory model specification , Shielding the access differences of various hardware and operating systems , To ensure the Java Program access to memory under various platforms can ensure the mechanism and specification of consistent effect . You can avoid things like c++ Memory models that directly use physical hardware and operating system have different performance under different operating systems and hardware platforms , Such as some c/c++ The program may be in windows The platform is working properly , And in the linux There's a problem with the platform .
Be careful JMM And JVM The difference of memory partition ：
JMM It describes a set of rules , Around atomicity 、 Order and visibility unfold ;
Similarities ： There are shared areas and private areas
Java The communication between threads is based on the shared memory model , The shared memory model mentioned here refers to Java Memory model ( abbreviation JMM),JMM Determines when a thread's write to a shared variable is visible to another thread . From an abstract point of view ,JMM The abstract relationship between thread and main memory is defined ： Shared variables between threads are stored in main memory （main memory） in , Each thread has a private local memory （local memory）, The thread is stored in local memory to read / Write a copy of the shared variable . Local memory is JMM An abstract concept of , It doesn't really exist . It covers caching , Write buffer , Registers and other hardware and compiler optimizations . From the picture above , Threads A With threads B If you want to communicate with each other , Must go through the following 2 A step ：
Threads A Put the local memory A The shared variables updated in are refreshed to main memory .
Threads B Read threads into main memory A Previously updated shared variables .
Specific schematic diagram ： As shown in the figure above , Local memory A and B There are shared variables in main memory z Copy of . Suppose at the beginning , Of these three memories z Values are 0. Threads A When executed , Put the updated z value （ Let's say it's 1） Temporarily stored in your own local memory A in . When a thread A And thread B When communication is needed , Threads A First of all, I will modify my local memory z Value is flushed to main memory , In main memory at this time z The value changes to 1. And then , Threads B Read threads into main memory A Updated z value , The thread B Of local memory z Value also becomes 1.
On the whole , These two steps are essentially threads A On the thread B Send a message , And this communication process must go through main memory .JMM By controlling the interaction between the main memory and the local memory of each thread , for java Programmers provide memory visibility guarantees .
3.1 JVM Yes Java Implementation of memory model
stay JVM Inside ,Java Memory model put Java The virtual machine is divided into ： Thread stack and heap
Thread stack ：
Each one runs in Java All threads in a virtual machine have their own thread stack . This thread stack contains information about the current execution point of the method called by this thread . A thread can only access its own thread stack . Local variables created by one thread are not visible to other threads , Visible only to yourself . Even if two threads execute the same code , These two threads are still in their own thread stack code to create local variables . therefore , Each thread has a unique version of each local variable .
Thread heap ：
The heap is contained in Java All objects created in the program , No matter which object is created . This includes the object version of the original type . If an object is created and assigned to a local variable , Or as a member variable of another object , This object is still stored on the heap .
If a local variable is of primitive type , Then it will be completely stored in the stack area
A local variable can also be a reference to an object , In this case , This local reference will be stored in the stack , But the object itself is still stored in the heap
For a member method of an object , These methods contain local variables , It still needs to be stored in the stack area , Even if the objects they belong to are in the heap area
For a member variable of an object , Whether it's the original type or the packaging type , Will be stored in the heap area
Static The variables of the type and the information about the class itself are stored in the heap area along with the class itself
Objects in the heap can be shared by multiple threads . If a thread gets an application of an object , It can then access the member variables of this object . If two threads call the same method of the same object at the same time , Then these two threads can access the member variables of this object at the same time , But for local variables , Each thread will copy one copy to its own thread stack
3.2 Java Bridge between memory model and hardware architecture
Java The memory model is not consistent with the hardware memory architecture . There is no distinction between stack and heap in hardware memory architecture , From the perspective of hardware , Whether it's stacks or heaps , Most of the data will be stored in main memory , Of course, some stack and heap data may also be stored in CPU In the register , As shown in the figure below ,Java There is a cross relationship between memory model and computer hardware memory architecture ：
3.3 Java Memory model - Synchronize eight operations
1) lock( lock )： A variable acting on main memory , Identifies a variable as a thread exclusive state 2) unock( Unlock )： A variable acting on main memory , Release a variable that is locked , Freed variables can be locked by other threads 3) read( Read )： A variable acting on main memory , Transfers a variable value from main memory to the thread's working memory , For subsequent load The action to use 4) load( load )： A variable acting on working memory , It is the read The operation places the values of the variables obtained from main memory into a copy of the variables in working memory 5) use( Use )： A variable acting on working memory , Passes the value of a variable in working memory to the execution engine 6) assign( assignment )： A variable acting on working memory , It assigns a value received from the execution engine to a variable in the working memory 7) store( Storage )： A variable acting on working memory , Transfer the value of a variable in working memory to memory , For subsequent write The operation of 8) write( write in )： A variable acting on working memory , It is the store Operations are passed from the value of a variable in working memory to the variable in main memory
3.4 Java Memory model - The synchronization rules
If you want to copy a variable from main memory to working memory , You need to do it sequentially read and load operation , If you synchronize variables from working memory back to main memory , You have to do it sequentially store and write operation . but Java The memory model only requires that the operations must be performed in sequence , There is no guarantee that the execution must be continuous
Don't allow read and load、store and write One of the operations occurs separately
A thread is not allowed to discard its nearest assign The operation of , That is, variables must be synchronized to main memory after they have changed in working memory
A thread without reason is not allowed （ It didn't happen assign operation ） Synchronize data from working memory back to main memory
A new variable can only be created in main memory , It is not allowed to use an uninitialized one directly in working memory （load or assign） The variable of . That is to say, to implement a variable use and store Before the operation , Must be executed first assign and load operation
Only one thread is allowed to work on a variable at a time lock operation , but lock The operation can be executed multiple times by the same thread , Multiple execution lock after , Only execute the same number of times unlock operation , Variables will unlock .lock and unlock They have to come in pairs
If you execute on a variable lock operation , Will empty the value of this variable in working memory , The variable needs to be reexecuted before the execution engine can use it load or assign The operation initializes the value of the variable
If a variable is not previously lock Locking operation , It is not allowed to be executed unlock operation , I'm not allowed to go unlock A variable that is locked by another thread
Execute on a variable unlock Before the operation , You must first synchronize this variable to main memory ( perform store and write operation )
Atomicity 、 visibility 、 Orderliness ： Check out my last article ： Thread security details ( Atomicity 、 visibility 、 Orderliness )
Four 、 The advantages and risks of concurrency
advantage ：1) Speed ： Use to process multiple requests , More responsive , Complex operations can be performed simultaneously by multiple processes 2) Design ： Programming is simpler in some cases , There can also be more options 3) Resource utilization ：CPU Be able to wait IO When you do something else
risk ：1) Security ： When multiple threads share data, it may result in inconsistent results 2) Activity ： When an operation cannot continue , There will be life leaping problems . For example, deadlock. 、 Hunger and so on 3) performance ： Too many threads can cause ：CPU Switch frequently , More scheduling time ; Synchronization mechanism ; Consume too much memory
5、 ... and 、 summary
CPU Multi level cache ： Cache consistency 、 Out of order optimization Java Memory model ：JMM Regulations 、 Abstract structure 、 Synchronize eight operations and rules Java The advantages and risks of concurrency