TPS： Transactions per second .
1. JAVA Memory model
JAVA The main memory and working memory are organized into two parts .
(1) Main memory
Shared by all threads . It mainly includes local method area and heap .
(2) The working memory
Each thread has a working memory , Not shared . Working memory consists of two parts .
l The thread's private stack
l Main memory part of the variable copy of the register （ Program timer PC And the working tell buffer ）
(3) Memory to memory interaction
In order to facilitate the understanding of inter memory operations , It needs to be understood that it is the memory operation between those parts . There are three main parts ： Main memory 【lock、unlock、read、store、write】、 Working memory and execution engine .
Main memory ：【lock、write、unlock】
Main memory -> The working memory ：【read】
The working memory ：【load】=》read The result of the assignment is assigned to a copy of the variable in working memory .
The working memory -> Execution engine ：【use】
Execution engine -> The working memory ：【Assign】
The working memory -> Main memory ：【store】
Main memory ：【write】=》
Separate execution engine ：
l Lock( lock )： Variables acting on main memory , Mark a variable as a thread exclusive state .
l Read( Read )： Variables acting on main memory , Transfer the value of a variable from main memory to the working memory of the thread .
l Load( load )： Variables in working memory , hold read The value of the variable obtained from main memory is put into the variable copy in working memory .
l Use( Use )： Variables in working memory , Pass the value of a variable in working memory to the execution engine .
l Assign( assignment )： Variables in working memory , Assign a value received from the execution engine to a variable in working memory .
l Store( Storage )： Variables in working memory , Transfers the value of a variable in working memory to main memory .
l Write( write in )： Variables acting on main memory , hold store The value of the variable obtained by the operation from working memory is put into the variable in main memory .
l Unlock( Unlock )： Variables acting on main memory , Release a variable that is locked , After that, it can be locked by other threads .
l Read variables from main memory to working memory , Must be carried out in sequence read、load
l To synchronize variables from working memory back into main memory , Must be carried out in sequence store、write
(4) volatile Special rules for type variables
Volatile Provides a lightweight means of synchronization . Only multi thread visibility is guaranteed , Can't guarantee the order of multithreading .
any volatile Decorated variable , Do not copy copies to working memory . Any changes are written to main memory in time . therefore , about volatile Modification of modified variables , All threads can see it immediately . But there's no guarantee that the changes are orderly .
Volatile How to achieve visibility . Modification of variables , Immediately synchronize to main memory . Before threads are used , Synchronize from main memory .
Synchronize The visibility of synchronization blocks is “ For a variable unlock Before , You have to synchronize variables into main memory ” This rule gets .
l Atomicity under satisfied conditions
If you use volatile To achieve thread safety . The following conditions need to be met ：
- The write operation of the variable does not depend on the current value of the variable .
- This variable is not included in invariants with other variables .
l When the long and double Type variables with keywords volatile When decorating , You can get a simple operation （ Assignment and （return) The atomicity of .
l Disables instruction reorder optimization
Ensure consistency by inserting a memory barrier .
(5) Atomicity 、 visibility 、 Orderliness
Definition ： To put it simply , Atomic operations are those that cannot be interrupted , This operation has not started yet , Or it's all done .
Java The memory model guarantees atomic operations read、load、use and assign、store、write.
Lock and unlock Can guarantee a wider range of atomicity .
Synchronize Atomicity is the use of higher-level bytecode instructions monitorenter and monitorexit To implicitly operate .
Definition ： Visibility is when a thread changes the value of a shared variable , Other threads are immediately aware of the change .
l Volatile :volatile The special rule of the new value ensures that the new value can be synchronized to the main memory immediately . Ensure that the variables are refreshed from main memory before each use . therefore , Ensures visibility between multiple threads .
l Synchronize ： Synchronization block visibility , from “ Execute on a variable unlock Before , Must be synchronized to main memory ” This rule gets .
l Final：final Once the constructor method initialization assignment is completed , Variable values are not modified . The variables obtained by each thread are assigned after initialization . It won't change .
l If you observe in this thread , All operations are orderly . If you look at one thread at another , All operations are unordered . The first half of the sentence refers to “ The semantics realized in a thread as serial ”, The second half of the sentence refers to “ Command rearrangement ” and “ Working memory and main memory synchronization delay ” The phenomenon .
l Java adopt volatile and synchronize Two keywords to ensure that the operation between threads is orderly .Volatile By itself, command rearrangement is prohibited .Synchronize adopt “ Only one thread is allowed to process a variable at the same time lock operation ”, Therefore, two synchronization blocks of the same lock can only be entered serially .
(6) Antecedent principle
First occurrence is java The partial order relation between two operations is defined in the memory model . If you operate A First occurs in operation B, In fact, it means that the operation occurs B When , operation A The impact of the operation B It's observable . The effects include “ Values of shared variables in memory 、 Sent a message 、 Method called, etc ”
That is to say happens-before principle . The principle is to judge whether the data is There is competition 、 Whether threads are safe The main basis of . First occurrence is Java Partial order relationship between two operations defined in memory model .
2. JAVA Threads
CPU And the understanding of the kernel ：
CPU It's the abbreviation of CPU . And the kernel is CPU At the heart of .CPU Contains multiple cores .
(1) Implementation of threads
Using kernel thread implementation
Kernel threads are threads directly supported by the operating system kernel , This kind of thread is implemented by the kernel, switching on each thread , The kernel operates the scheduler to schedule through multithreading , And is responsible for mapping the tasks of the thread to each processor , Each kernel thread can be regarded as a separate part of the kernel , A multithreaded kernel is called a multithreaded kernel
Threads supported by the operating system kernel , This kind of thread is switched by the kernel . Programs generally don't use kernel threads directly , It's a high-level interface using kernel threads ---LWP（ Lightweight process ）-- Lightweight process is a high-level interface of kernel thread Because of kernel support , Every lightweight process , There is a separate kernel level thread support . It's easy to understand , A lightweight process blocks , Does not affect the work of other threads 【 Because there is independent kernel support 】.
Because of the Kernel Implementation , Therefore, the cost of various operations of the thread is high 【 All kinds of operations need to use system calls , At the same time, it needs to be in the user mode （user mode） And kernel state （kernel mode） Before switching back and forth 】. The number of cores is fixed . therefore , The number of kernel threads is also certain .
Implementation using user threads
User thread values are built entirely on the thread library in user space , This thread does not need to switch kernel state . High efficiency and low consumption . It also supports a larger number of threads . Part of the high-performance database multithreading is the use of user threads to achieve .
Personal understanding （ I'm not sure it's right ）： User space for java In terms of procedure , Namely JAVA virtual machine JVM. and
The relationship between a process and a user thread is 1 Yes N The relationship between .
(2) Thread scheduling
Thread scheduling refers to The process of assigning processor permissions to threads . There are two kinds , They are collaborative thread scheduling and preemptive thread scheduling .
Collaborative thread scheduling
Thread execution time is controlled by the thread itself . After the thread completes its own operation , Actively notify the system to switch to another thread . benefits ： Implement a simple , And the switch is known to the thread itself . There is no thread synchronization problem . shortcoming ： If a thread blocks , The whole process will block 【 You can't give up CPU】.
Preemptive thread scheduling
Thread execution time has system allocated execution time . Thread switching is not determined by the thread itself . The thread execution time system is controllable , There won't be a single thread blocking the entire process .
JAVA Thread scheduling is preemptive thread scheduling .
(3) User mode and kernel mode
Purpose ： In order to prevent the program from accessing resources arbitrarily , Most of CPU Architecture supports Kernel mode And User mode Two execution modes .
And zero copy technology .
Kernel mode (Kernel Mode)
In kernel mode , The code has all control rights over any hardware . Can perform all of CPU Instructions , Can access any address memory . Kernel mode is the bottom layer of the operating system , The most trusted function service . In kernel mode , Any exception is catastrophic . It may cause the whole machine to go down .
User mode (User Mode)
In user mode , The code has no control over the hardware . You can't access the address memory directly . Programs access hardware and memory through the system interface . In this mode of protection , Even if the program crashes , It's also recoverable .
Switch between user mode and kernel mode
All user programs run in user mode , But sometimes a program does need to do something kernel like , For example, reading data from a hard disk , Or get input from the keyboard . And the only thing that can do these things is the operating system , So at this point, the program needs to first request the operating system to perform these operations in the name of the program .
This requires a mechanism like this : User mode program switch to kernel mode , But you can't control the instructions executed in kernel mode
This mechanism is called system call , stay CPU The implementation in is called a trap instruction (Trap Instruction)
Their workflow is as follows :
1． User mode programs put some data values in registers , Or create a stack with parameters (stack frame), In this way, it shows that the service provided by the operating system is needed .
2． User mode program execution trap instruction
3．CPU Switch to kernel state , And jump to the instruction at the specified location in memory , These instructions are part of the operating system , They have memory protection , Not accessible by user mode programs
4． These instructions are called traps (trap) Or the system call processor (system call handler). They read data parameters that the program puts into memory , And execute the service requested by the program
5． After the system call is completed , The operating system will reset CPU In user mode and return the result of system call
In the user program , Running in user mode user mode Next , The hardware needs to be manipulated . First , The program cannot operate directly on the hardware , So call the system function interface . then , Detecting calls 、 Authority verification, etc . No problem later , Notice again CPU Switch to kernel Pattern . Execute the privilege instruction according to the parameters passed by the application . When the program is finished , The system call notifies CPU Switch to user mode , And back to the application .
Why do you want to use user state and kernel state
Because of the need to limit access between different programs , To prevent other programs from accessing memory , Or get peripheral data , And send it to the network , CPU There are two levels of authority -- User mode and Kernel mode