Java multi-thread mechanism series: (4) volatile and Command Re-sorting (happen-before)

Source: Internet
Author: User

I. volatilevolatile, which has to be mentioned, is a very old keyword. It was born almost with the birth of JDK. We all know this keyword, but we don't know when to use it; this keyword is everywhere in JDK and open-source frameworks, but concurrent experts often suggest us stay away from it. For example, Thread is a basic class. The most important thread status field is modified using volatile. for details, see code/* Java Thread status for tools, * initialized to indicate thread 'Not yet started' */private volatile int threadStatus = 0. As mentioned above, concurrency experts suggest us stay away from it, especially when the performance of the synchronized keyword of JDK 6 is greatly optimized, it is rarely used, but it is still a keyword worth studying, the significance of studying it is not to use it, but to understand it is helpful for understanding the entire multi-thread mechanism of Java. 1. let's take a look at the role of volatile. The following code starts: 1: public class VolatileExample extends Thread {2: // sets the class static variables. Each Thread accesses the same shared variable 3: private static boolean flag = false; 4: 5: // infinite loop. Wait until the flag changes to true. 6: public void run () {while (! Flag) {};} 7: 8: public static void main (String [] args) throws Exception {9: new VolatileExample (). start (); 10: // sleep aims to wait until the Thread starts up, that is, the infinite loop body that enters the run is 11: Thread. sleep (100); 12: flag = true; 13:} 14:} This example is well understood. Start a thread in the main function, the run method is an infinite loop with flag as the flag. If the flag is true, the loop jumps out. When the main statement is executed to 12 rows, the flag is set to true. based on logical analysis, the thread ends, that is, the entire program is executed. Run the command to see what the result is? The results are surprising, and the program will never end. Main is definitely over, because the run method of the thread is not over, that is, the flag in the run method is still false. Add the volatile modifier to line 1, that is, private static volatile boolean flag = false. Run the command again? As a result, the program Exits normally and volatile takes effect. Let's modify it. Remove the volatile keyword, restore to the initial example, and then (! Flag) {} changed to while (! Flag) {System. out. println (1) ;}, run it again. By analysis, the program will not end when there is no volatile keyword. Although a print statement is added, no keyword/logic modification is made, and the program will not end, but the execution result is: The program ends normally. With these perceptual knowledge, let's analyze the semantics of volatile and its role. 2. volatile semantics the first semantics of volatile is to ensure the visibility of variables between threads. Simply put, after thread A modifies the variable X, other threads executed after thread A can see the change of variable X. More specifically, they must comply with the following two rules: After the thread modifies the variable, it should immediately write back to the main memory. When a thread reads a variable, it must read it from the main memory rather than cache it. To explain this problem in detail, you have to mention the Java Memory Model (JMM ). The memory model of Java is a complex topic. It falls into the scope of Java language specifications and has a limited personal level. It cannot be fully described in a limited space. If you need to understand it clearly, learn more about Java Virtual Machine-JVM advanced features and best practices and The Java Language Specification, Java SE 7 Edition. Here, I will briefly cite some materials for further explanation. Java needs to define its own memory model to ensure its platform and isolate Java applications from the memory model of the operating system. In the Java memory model, the memory is divided into two parts: the main memory and the working memory. The main memory is shared by all threads, and the working memory is allocated by each thread, the working memory of each thread is independent and invisible to each other. When the thread starts, the virtual machine allocates a working memory for each memory, which not only contains the local variables defined inside the thread, it also contains copies of the shared variables (objects not constructed in the thread) required by the thread, that is, to improve the execution efficiency, reading a copy is faster than directly reading the primary memory (here we can simply think of the primary memory as a heap in a virtual machine, and the working memory as a stack (or virtual machine stack ), stack is a small continuous space and sequential inbound to the stack, while stack is a large non-consecutive space, so the addressing speed in the stack is much faster than the heap ). Data exchange between the active memory and the active memory is performed through the active memory. For example, at the same time, the Java memory model also defines a series of rules for interaction between the working memory and the main memory and the sequence of operations (these rules are also complex, for more information, see Chapter 12.3.2 of Java Virtual Machine-JVM advanced features and best practices. For shared common variables, after the Variables change in the working memory, they must be written back to the working memory (sooner or later, but not immediately ), however, the volatile variable requires that the variable be written back to the working memory immediately after it changes in the working memory. When the thread reads the volatile variable, the latest value must be retrieved immediately in the working memory instead of reading A copy of the local working memory. This rule ensures that "When thread A modifies variable X, other threads executed after thread A can see the change of variable X ". Most of the online articles have explained volatile so far, but I think there are still some omissions and I will discuss them. The working memory is a cache of the primary memory. To avoid cache inconsistency, volatile needs to discard the cache. However, in addition to the memory cache, there is also a cache at the CPU Hardware level, that is, a register. If thread A changes the variable X from 0 to 1, the CPU operates in its cache and does not return to the memory in time, therefore, the JVM cannot be seen by thread B that can be executed in a timely manner. Therefore, I think that when JVM is processing the volatile variable, the hardware-level cache consistency principle is also used. (For the CPU cache consistency principle, see Java multi-thread mechanism series: (2) cache consistency and CAS. The second semantics of volatile: disable command re-sorting. For more information about Command Re-sorting, see the "Command Re-sorting" section. This is a major application scenario of volatile.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.