volatile keyword
The volatile keyword can modify the member variables and static variables of the class
The role of the volatile keyword
1. Guarantee the visibility of the modified attribute. If the modified attribute is changed, other threads will be immediately visible
2. Ensure the order of the modified attributes, and the modified attributes are prohibited from modifying the order of instruction execution
Note: The volatile keyword does not guarantee the atomicity of properties
The underlying principle
Orderliness: After (memory barrier instruction) is modified by volatile, a memory barrier instruction will be applied to the variable, and the reordering of instructions is prohibited to ensure the orderliness of instructions
Visibility: After (Lock prefix instruction + cache coherence protocol MESI) is modified by volatile, a Lock prefix instruction will be added to the variable. After the attribute is modified, an instruction with a Lock prefix will be issued to the CPU to trigger sniffing of each CPU. After sniffing the value of the development mainline and modifying it, the value in its cache will expire and be reassigned
resolve atomicity
Atomic solution has two options
1. Locking the code that modifies shared variables is a blocking implementation
2. Use the atomic variables provided by the atomic class, non-blocking implementation
The JUC package is provided in java to provide atomic classes in concurrent programming
The atomicity of the atomic class is realized by the volatile+CAS mechanism
CAS mechanism
The full name of CAS is: Compare-And-Swap comparison and exchange, which is supported at the hardware level
CAS is an implementation of an optimistic lock, a lightweight lock based on the idea of a spin lock, suitable for situations where the amount of concurrency is relatively small
The three operands in CAS
V: memory value, refers to the value of the shared variable in the main memory
A: Estimated value
B: update value
principle:
When the CPU reads a shared variable, it will store a copy of the read variable value in the working memory and use it as an estimated value
After the CPU operates on the variable, it is stored as an updated value
When updating the value of the main memory, it will first use whether the estimated value is consistent with the memory value. If it is consistent, the operation can be performed. If it is inconsistent, the value read from the main memory will be rewritten and the algorithm will be executed again.
advantage
It is a non-blocking implementation without adding locks, which can improve the execution efficiency of the program
Improve CPU utilization
No lock, all threads can access
shortcoming
The spin lock will continue to loop and judge, and it is easy to occupy a large amount of CPU resources.
Only suitable for small concurrency situations, if the request volume is large, the CPU load capacity is limited
ABA questions
The ABA problem refers to that if two threads modify the shared variable during the execution of the shared variable by one thread, and the last modified value is the same as the value before the modification by the two threads
For example: shared variable a="A"
Thread 1 reads a="A"
Thread 2 modifies a="B"
Thread 3 modifies a="A"
At this time, thread 1 cannot determine whether the value of the shared variable has been modified.
Solution: Add a version number to the shared variable, and compare the version number every time you operate the shared variable.