In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article introduces the relevant knowledge of "what is the volatile mechanism". In the operation of actual cases, many people will encounter such a dilemma. Then let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
Summary of premises
We all know the characteristics of synchronized keywords: atomicity, visibility, ordering, and reentrance. although JDK is constantly trying to optimize this built-in lock, it is mentioned in this article that there are four states: no lock-> bias lock-> lightweight lock-> weight lock. However, in the case of high concurrency and a large number of conflicts occur, it will eventually expand to the weight lock.
Why do you say that?
That's because synchronized is a synchronous code block, and the whole code block is atomically manipulated through the monitor monitor (the method is to determine the ACC_SYNCHRONZED flag bit on the whole method). Volatile is atomic for a single operation and non-atomic for a non-single operation.
Basic usage
The volatile keyword in the Java language is used to modify variables, as shown below. This variable needs to be stored directly in main memory.
Public class SharedClass {public volatile int counter = 0;}
Int counter variables modified by the volatile keyword are stored directly in main memory. And all reads to the variable are read directly from the main memory, not directly from the CPU cache. (don't worry about the difference between main memory and CPU cache if you don't understand it, which will be described in more detail below)
What problem does this solve? There are mainly two questions:
The problem of multithreading visibility
The problem of reordering CPU instructions
Note: for ease of description, we will next refer to volatile-decorated variables as "volatile variables" and build variables that are not decorated with volatile as "non-volatile" variables.
Understand the volatile keyword
Variable visibility issues (Variable Visibility Problem): volatile ensures the visibility of variable changes across multiple threads.
In a multithreaded application, for the sake of computing performance, each thread copies the variable from the main memory to the cache of the thread's CPU by default, and then reads and writes. Now computers are basically multi-core CPU, different threads may run on different cores, and each core will have its own cache space. As shown in the following figure (CPU 1 and CPU 2 in the figure can be directly understood as two cores):
The problem here is that JVM does not guarantee when the data in the CPU cache will be written to main memory, nor when it will be read from main memory to the CPU cache. In other words, threads on different CPU may read different values for the same variable, which is what we usually say: invisibility between threads.
For example, in the following figure, the modified counter = 7 of Thread 1 is only visible in the cache of CPU 1. When Thread 2 reads the counter variable on its own CPU 2 cache, the value of the variable counter is still 0.
One of the purposes of volatile is to solve the invisibility between threads. Variables modified by volatile will become visible between threads.
The solution is what is mentioned at the beginning of the article:
With a variable modified by volatile, all reads to that variable are read directly from main memory, rather than from CPU's own cache. And all the writing exercises for this variable are written to the main memory.
Because the main memory is shared by all CPU, it is only natural that even threads on different CPU can see other threads modify this variable. Volatile doesn't just guarantee the visibility of volatile variables, but volatile actually does more on visibility than volatile variables:
When Thread A modifies a volatile variable V, another Thread B immediately reads the variable V. Once Thread B reads the variable V, not only the variable V is visible to Thread B, but all variables visible to Thread A before Thread A modifies the variable V will be visible to Thread B.
When Thread A reads a volatile variable V, all other variables visible to Thread An are also read from main memory.
Visibility of characteristics and principles
Any thread modifies the variable modified by volatile, and other threads can immediately recognize the latest value. The principle of achieving visibility is as follows.
Step 1: modify the local memory and force it to be flushed back to the main memory.
Step 2: force the working memory of other threads to expire. (this part belongs more to the MESI protocol)
Individual read / write is atomic
The read / write of a single volatile variable (such as vl=l) is atomic, and the compound operation (such as iTunes +) is not atomic. The Demo code is as follows:
Public class VolatileFeaturesA {private volatile long vol = 0L; / * * single read atomicity * @ date:2020 14 July 2002 5:02:38 p.m. / public long get () {return vol } / * individual writings are atomic * @ date:2020 July 14, 2002 5:01:49 * / public void set (long l) {vol = l } / * compound (multiple) read and write are not atomic * @ date:2020, July 14, 2002 5:02:24 pm * / public void getAndAdd () {vol++;}} mutually exclusive
Only one thread is allowed to manipulate volatile variables at a time, and volatile-decorated variables can also achieve the effect of locking in unlocked scenarios, similar to mutexes. The above VolatileFeaturesA.java and the following VolatileFeaturesB.java classes implement the same functionality (except for the getAndAdd method).
Public class VolatileFeaturesB {private volatile long vol = 0L; / * * ordinary write operations * @ date:2020 8:18:34 on July 14, 2000 * @ param l * / public synchronized void set (long l) {vol = l } / * * add 1 operation * @ author songjinzhou * @ date:2020 July 14, 8:28:25 * / public void getAndAdd () {long temp = get (); temp + = 1L; set (temp) } / * * ordinary read operation * @ date:2020 8:33:00 on July 14, 2000 * @ return * / public synchronized long get () {return vol;}} partial ordering
JVM uses a memory barrier to prevent instruction rearrangement so as to achieve partial ordering. Take a look at the following Demo code analysis to see why it is only partially ordered:
/ / a, b are ordinary variables, flag is the volatile variable int a = 1; / / code 1int b = 2; / / code 2volatile boolean flag = true; / / code 3int a = 3; / / code 4int b = 4; / / code 5
Because flag variables are decorated with volatile, code 3 will not be placed before code 1 and code 2, nor will code 3 be placed after code 4 or code 5 when reordering instructions. However, the order of instruction rearrangement time code 1 and code 2, code 4 and code 5 is not within the range of prohibited rearrangement, for example, code 2 may be moved before code 1.
There are four types of memory barriers.
LoadLoadBarriers
Instruction example: LoadA-> Loadload-> LoadB
This barrier ensures that both LoadB and subsequent read instructions can read the data loaded by the LoadA instruction, that is, the read operation LoadA must be executed before LoadB.
StoreStoreBarriers
Instruction example: StoreA-> StoreStore-> StoreB
This barrier ensures that StoreB and subsequent write instructions can manipulate the data after the execution of the StoreA instruction, that is, the write operation StoreA must be executed before StoreB.
LoadStoreBarriers
Instruction example: LoadA-> LoadStore-> StoreB
This barrier ensures that the StoreB and subsequent write instructions can read the data loaded by the LoadA instruction, that is, the read operation LoadA must be executed before the write operation StoreB.
StoreLoadBarriers
Instruction example: StoreA-> StoreLoad-> LoadB
This barrier ensures that both the LoadB and subsequent read instructions can read the data after the execution of the StoreA instruction, that is, the write operation StoreA must be executed before the read operation LoadB.
The principle of order:
If an attribute is decorated with volatile, the four types of memory barriers described above are inserted before or after the attribute at compile time to prohibit instruction rearrangement, such as:
Insert StoreStoreBarriers in front of the volatile write operation to ensure that the normal read and write operation prior to the volatile write operation is completed before performing the volatile write operation.
Insert StoreLoadBarriers after the volatile write operation to ensure that the data after the volatile write operation is refreshed to the main memory, and that the subsequent volatile read and write operations can use the latest data (main memory).
Insert LoadLoadBarriers and LoadStoreBarriers after the volatile read operation to ensure that the ordinary read and write operation after the volatile read and write operation first sets the thread local variable to invalid, and then updates the shared variable of the main memory to the local memory, and then uses the local memory variable.
Volatile read memory barrier:
Volatile write memory barrier:
Status flags, such as Boolean status flags, as an identification of the completion of an important event, cannot rely on any other variables, as shown in the Demo code:
Public class Flag {/ / task completion flag, true: completed, false: incomplete volatile boolean finishFlag; public void finish () {finishFlag = true;} public void doTask () {while (! finishFlag) {/ / keep do task}}
One-time security release, for example: the famous double-checked-locking,demo code has been posted above. For low-cost reads, such as calculators, the Demo code is as follows.
/ * counter * / public class Counter {private volatile int value; / / read operations do not need to be locked, reducing synchronization overhead submission performance, using volatile modification to ensure the visibility of read operations, each time you can read the latest value public int getValue () {return value;} / / write operations use synchronized locking to ensure atomicity public synchronized int increment () {return value++ This is the end of the content of "what is the volatile mechanism". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.