Volatile in JAVA

Source: Internet
Author: User

In the concurrent processing of java threads, there is a big confusion in the use of the keyword volatile. I think this keyword can be used to achieve all-round concurrent processing. The Java language supports multiple threads. To solve the thread concurrency problem, the synchronous block and volatile keyword mechanism are introduced in the language.

Synchronized

Synchronization blocks are familiar to everyone and are implemented using the synchronized keyword. When synchronized and block statements are added, at the same time, only one thread can use synchronized to modify the method or code block.

Volatile

For variables modified with volatile, each time a thread uses a variable, it will read the most modified value of the variable. Volatile is easily misused for atomic operations. The following example shows how to implement a counter. Every time a thread starts, the counter inc method is called to add 1 to the counter.

Public class Counter {public static int count = 0; public static void inc () {// The delay is 1 millisecond, making the result obviously try {Thread. sleep (1);} catch (InterruptedException e) {} count ++;} public static void main (String [] args) {// start 1000 threads at the same time, perform I ++ calculation and check the actual result for (int I = 0; I <1000; I ++) {new Thread (new Runnable () {@ Override public void run () {Counter. inc ();}}). start ();} // The value of each running operation may be different, which may be 1000 System. out. println ("Run result: Counter. count = "+ Counter. count );}}

Running result: Counter. count = 995

The actual calculation result may be different each time. The result of the local machine is: running result: Counter. count = 995, we can see that in a multi-threaded environment, Counter. the expected result of count is 1000. Many people think that this is a multi-thread concurrency problem. You only need to add volatile before the variable count to avoid this problem. Let's modify the code to see if the result meets our expectations:

Public class Counter {public volatile static int count = 0; public static void inc () {// The delay is 1 millisecond, making the result obviously try {Thread. sleep (1);} catch (InterruptedException e) {} count ++;} public static void main (String [] args) {// start 1000 threads at the same time, perform I ++ calculation and check the actual result for (int I = 0; I <1000; I ++) {new Thread (new Runnable () {@ Override public void run () {Counter. inc ();}}). start ();} // The value of each running operation may be different, which may be 1000 System. out. println ("Run result: Counter. count = "+ Counter. count );}}

Running result: Counter. count = 992

The running result is still less than the expected 1000. The reason is as follows: in the java garbage collection article, the memory allocation during jvm Runtime is described. One of the memory areas is the jvm Virtual Machine stack. Each thread has a thread stack during running, and the thread stack stores the variable value information during running. When the thread accesses a value of an object, it first finds the value of the variable corresponding to the heap memory through the object reference, load the specific value of the heap memory variable to the local memory of the thread and create a copy of the variable. Then, the thread no longer has any relationship with the variable value of the object in the heap memory, instead, the value of the copy variable is directly modified. At a certain time point after modification (before the thread exits), the value of the copy of the thread variable is automatically written back to the object's heap variable. In this way, the value of the object in the heap changes. The following figure describes these interactions:


Read and load: copy the variable from the primary memory to the current working memory.
Use and assign run the code to change the value of the shared variable.
Store and write

Here, use and assign can appear multiple times

However, these operations are not atomic, that is, after the read load, if the count variable in the main memory is modified, the value in the thread's working memory will not change because it has been loaded, therefore, the calculated results are different from the expected ones. For variables modified by volatile, the jvm Virtual Machine only ensures that the value loaded from the main memory to the thread's working memory is up-to-date. For example, if thread 1, thread 2 are performing read and load operations, if the count value in the main memory is 5, the latest value will be loaded. After the thread 1 heap count is modified, it will be written to the main memory, and the count variable in the main memory will change to 6. Because thread 2 has been performing the read and load operations, after the operation, it will also update the variable value of the main memory count to 6, resulting in two threads that use the volatile keyword to modify, there will still be concurrency.

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.