The volatile keyword does not function as a thread counter

Source: Internet
Author: User

In Java thread concurrency processing, there is a very big confusion about the use of a keyword volatile, for the use of this keyword, in the multi-threaded concurrent processing can be all right.

The Java language is multi-threaded, and in order to solve the problem of thread concurrency, the synchronization block and the volatile keyword mechanism are introduced inside the language.

synchronized

Synchronization block Everyone is more familiar with the Synchronized keyword to achieve, all plus synchronized and block statements, in multi-threaded access, at the same time only one thread can be used

Synchronized a modified method or block of code.

Volatile

With volatile modifiers, the thread will read the variable's most-modified value each time it uses the variable. Volatile is easily misused and used for atomic operations.

Here is an example, we implement a counter, each time the thread starts, the Counter Inc method is called, the counter is added a

Execution Environment--JDK version: jdk1.6.0_31, Memory: 3G cpu:x86 2.4G

public class Counter {public static int count = 0;        public static Void Inc () {//Here is delayed by 1 milliseconds, making the result obvious try {thread.sleep (1);    } catch (Interruptedexception e) {} count++; } public static void Main (string[] args) {//Start 1000 threads at the same time to perform i++ calculations to see the actual results for (int i = 0; i <; i++                    ) {New Thread (new Runnable () {@Override public void run () {                Counter.inc ();        }}). Start ();    }//The value of each run here may be different, may be System.out.println ("Run Result: counter.count=" + counter.count); }}
Running Result: counter.count=995
The results of the actual operation may be different each time, the result of this machine is: Running result: counter.count=995, you can see, in the Multi-threaded environment, Counter.count did not expect the result is 1000
public class Counter {public    volatile static int count = 0;    public static Void Inc () {        //Here is delayed by 1 milliseconds, making the result obvious        try {            thread.sleep (1);        } catch (Interruptedexception e) { c6/>}        count++;    }    public static void Main (string[] args) {        //start 1000 threads at the same time, go to the i++ calculation and see the actual result for        (int i = 0; i <; i++) {            New Thread (New Runnable () {                @Override public                void Run () {                    counter.inc ();                }            }). Start ();        }        There may be different values for each run, which may be        System.out.println ("Run Result: counter.count=" + Counter.count);}    }

Running Result: counter.count=992

The results of the operation is still not what we expected 1000, let us analyze the reasons below

In the Java garbage collection article, the allocation of memory at runtime of the JVM is described. One of the memory areas is the JVM virtual machine stack, and each thread runs with a line stacks,

Line stacks saves the variable value information when the thread runs. When a thread accesses an object, the value of the variable that corresponds to the heap memory is first found by the object's reference, and then the heap memory

The specific value of the variable is load into the thread's local memory, a copy of the variable is created, and then the thread is no longer related to the object in the heap memory variable value, but directly modifies the value of the replica variable.

At some point after the modification (before the thread exits), the value of the thread variable copy is automatically written back to the object in the heap variable. This changes the value of the object in the heap. Here is a picture

Describe this write interaction

Read and load copy variables from main memory to current working RAM
Use and assign execute code, change shared variable value
Store and write refresh main memory related content with work-in-RAM data

Where use and assign can appear multiple times

However, these operations are not atomic, that is, after read load, if the main memory count variable is modified, the value in the thread's working memory will not change because it has been loaded, so the computed result will not be the same as expected

For volatile-modified variables, the JVM virtual machine simply guarantees that the value from main memory load to the working memory of the thread is up-to-date

For example, if thread 1, thread 2 in the read,load operation, found that the value of count in main memory is 5, then the latest value will be loaded

After the thread 1 heap count is modified, it is write to main memory, and the count variable in main memory becomes 6

Thread 2 because the read,load operation has been performed, after the operation, the main memory will also be updated count of the variable value of 6

When two threads are modified with the volatile keyword in a timely manner, there is still a concurrency situation.

The volatile keyword does not function as a thread counter

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.