Java Multithreading (vi) in-depth understanding of Volitale keywords

Source: Internet
Author: User

Reprint Please specify Source:http://blog.csdn.net/xingjiarong/article/details/47945849
We continue to discuss multithreaded programming in Java, and today we are going to learn about another keyword--volitale in Java multi-threading.

First, Java memory model and multi-threaded programming in three of the gratitude

1. Atomic Nature

Atomicity means that some operations, or all, or none of them, the whole operation as a whole is inseparable, for example, there are two accounts in a bank, A, B, now to transfer from a account of 500 to the account of a, then there can be divided into two steps:
1. Withdraw 500 yuan from a account: a = A-500;
2. Deposit 500 RMB to B account: B = B + 500;
These two steps as a whole, or all do not execute, if only step one, then a account will be inexplicably lost 500 yuan, B account but nothing received.

In Java, read and assign operations to variables of the base data type are atomic operations, meaning that these operations are not interrupted, executed, or not executed.

For example:

i3;ii+3;i++;ij;

These four statements only the first statement is atomic, is the basic assignment operation. The other three statements, which appear to be atomic operations of assignment, are actually composed of multiple steps. For example i++ This statement is made up of the three statements of I,i+1,i=i+1, each of which is atomic, but it is not atomic.

2. Visibility

Visibility means that when multiple threads access the same variable, a thread modifies the value of the variable, and other threads can immediately see the modified value. For example:

//线程1i = 10;i = i+3;//线程2j=i;

In Java each thread has its own line stacks, and when a thread executes the required data, it copies the required data into memory into its own thread stack, then operates on the copy of the line stacks, and then writes the data back into memory after the operation is complete.

For example, thread 1 reads the value of I into its own thread stack and then adds 3 to I, but the operation is not written back to memory in a timely manner, so the value of I as seen by thread 2 at execution is still 3, which is the problem of visibility.

The Volitale keyword provided by Java can guarantee the visibility of the data.

3. Orderly Nature

Ordering: The order in which the program executes is executed in the order of the Code. We write the code in a sequential order, but that's just the order we see it, but when the compiler compiles it, it's going to rearrange the instructions, so the code might be executed in a different order than we thought. For example:

int0;              booleanfalse//语句31;                //语句1  true;          //语句2

The order of execution of statement 1 and statement 2 changes the results of the program without any effect, so this may change the order of the two instructions. So statement 2 will not be executed before statement 3, the answer is no, because statement 2 uses the variable declared in statement 3, then the compiler will limit the execution order of the statement to ensure the correctness of the program.

In a single thread, changing the order of instructions may not have undesirable consequences, but not necessarily in multi-threading. For example:

//线程1:context = loadContext();   //语句1true;             //语句2//线程2:while(!inited ){  sleep()}doSomethingwithconfig(context);

Since statement 1 and statement 2 do not have data dependencies, the compiler might reorder two instructions, and if you execute statement 2 first, thread 1 is blocked, then thread 2 's while loop condition is not satisfied, then execution goes down, but because the context is not assigned, it generates an error.

Second, the role of Volitale key words

The Volitale keyword guarantees visibility and some degree of ordering, but it does not guarantee atomicity.

1, volitale keyword guarantee visibility

Once a shared variable (a member variable of a class, a static member variable of a class) is modified by volatile, then there are two layers of semantics:

1) ensures the visibility of different threads operating on this variable, that is, one thread modifies the value of a variable, which is immediately visible to other threads.

2) command reordering is prohibited.

Look at a piece of code first, if thread 1 executes first, thread 2 executes:

//线程1booleanfalse;while(!stop){    doSomething();}//线程2true;

This code is a typical piece of code, and many people may use this notation when they break a thread. But in fact, is this code going to work exactly right? Is it bound to break the thread? Not necessarily, perhaps most of the time, this code can break the thread, but it can also lead to the inability to break threads (although this is a very small possibility, but as soon as this happens it will cause a dead loop).

The following explains why this code may cause the thread to fail. As explained earlier, each thread has its own working memory as it runs, and when thread 1 runs, it copies a copy of the value of the stop variable into its working memory.

Then when thread 2 changed the value of the stop variable, but before it could write to the main memory, thread 2 went to do something else, and thread 1 would have been looping because it did not know that thread 2 had changed the stop variable.

But it becomes different after the volatile modification:

First: Using the volatile keyword forces the modified value to be immediately written to main memory;

Second: With the volatile keyword, when thread 2 is modified, it causes thread 1 to work in-memory cache variable stop cache row is invalid;

Third: Because thread 1 works in-memory cache variable stop cache line is invalid, so thread 1 reads the value of the variable stop again to read the main memory.

Then thread 2 when modifying the stop value (of course, this includes 2 operations, modify the value in the thread 2 working memory, and then write the modified value to memory), will make thread 1 in the work in-memory cache variable stop cache row is invalid, and then threads 1 read, found that their cache row is invalid, It waits for the cache line corresponding to the main memory address to be updated, and then goes to the corresponding main memory to read the latest value.

Then thread 1 reads the latest correct value.

2. Volitale keyword does not guarantee atomicity

Knowing the volatile keyword above guarantees the visibility of the operation, but does volatile guarantee that the operation of the variable is atomic?

Let's look at an example:
  

 Public classTest { Public volatile intinc =0; Public void Increase() {inc++; } Public Static void Main(string[] args) {Final Test test =NewTest (); for(intI=0;i<Ten; i++) {NewThread () { Public void Run() { for(intj=0;j< +; j + +) Test.increase ();            };        }.start (); } while(Thread.activecount () >1)//Ensure that the previous thread finishes executingThread.yield(); System. out. println (Test.inc); }}

How much do you think the output of this program is? Maybe some friends think it's 10000. But in fact running it will find that each run results in an inconsistent, a number less than 10000.

Maybe some friends will have doubts, no Ah, the above is the variable Inc self-increment operation, because volatile guarantees the visibility, then in each thread after the INC self-increment, in other threads can see the modified value ah, so there are 10 threads have 1000 operations respectively, Then the value of the final Inc should be 1000*10=10000.

There is a misunderstanding here, the volatile keyword can ensure that the visibility is not wrong, but the above procedure is not able to guarantee the atomic nature. Visibility only guarantees the most recent value per read, but volatile has no way of guaranteeing the atomicity of the operation of the variable.

As mentioned earlier, the self-increment operation is not atomic, it includes reading the original value of the variable, adding 1 operations, writing to the working memory. That is, the three sub-operations of the self-increment operation may be split and executed, which may cause the following to occur:

If the value of the variable Inc is 10 at a time,

Thread 1 self-increment the variable, thread 1 reads the original value of the variable Inc first, and then thread 1 is blocked;

Thread 2 then self-increment the variable, thread 2 also reads the original value of the variable inc, because thread 1 only reads from the variable Inc, and does not modify the variable, so it does not cause the cache line of the working in-memory cache variable INC to be invalid for thread 2. So thread 2 will go directly to main memory to read the value of INC, find the value of INC 10, and then add 1 operations, and 11 write to the working memory, and finally write to main storage.

Then thread 1 then adds 1, since the value of the INC has been read, note that at this point the value of the in-Memory inc of Thread 1 is still 10, so that Threads 1 to Inc 1, and then 11 to the working memory, and finally to main storage.

Then, after two threads had a single self-increment operation, Inc increased by 1.

Explained here, there may be friends have doubts, no ah, the front is not to ensure that a variable when modifying volatile variables, will the cache row invalid? Then the other threads read the new value, yes, that's right. This is the volatile variable rule in the Happens-before rule above, but note that after thread 1 reads the variable, it is blocked, and the INC value is not modified. Then, although volatile ensures that the value read of the thread 2 pair of variable Inc is read from memory, thread 1 is not modified, so thread 2 does not see the modified value at all.

The source is here, the self-increment operation is not atomic, and volatile does not guarantee that any operation on the variable is atomic.

3, Volitale keyword to a certain extent to ensure the order of

It is mentioned that the volatile keyword can prohibit order reordering, so volatile can be guaranteed to a certain degree of order.

The volatile keyword prohibit command reordering has two layers of meaning:

1) When the program performs a read or write operation to a volatile variable, the changes in its preceding operation must have been made, and the result is already visible to the subsequent operation;

2) in the case of instruction optimization, you cannot put the statements that are accessed by volatile variables behind them, and you cannot put the statements that follow the volatile variable in front of them.

Maybe it's more about the above, for a simple example:

//x、y为非volatile变量//flag为volatile变量2;        //语句10;        //语句2true;  //语句34;         //语句4y = -1;       //语句5

Because the flag variable is a volatile variable, then in the process of order reordering, the statement 3 will not be placed in statement 1, Statement 2 before the statement 3 is not put into statement 4, statement 5 after. Note, however, that the order of statement 1 and Statement 2, Statement 4, and statement 5 are not guaranteed.

And the volatile keyword guarantees that execution to the statement 3 o'clock, Statement 1 and statement 2 must be completed, and statement 1 and statement 2 execution results to statement 3, Statement 4, Statement 5 is visible.

So let's go back to one of the examples above:

//线程1:context = loadContext();   //语句1true;             //语句2//线程2:while(!inited ){  sleep()}doSomethingwithconfig(context);

In the preceding example, it is mentioned that it is possible that statement 2 will be executed before statement 1, so long may cause the context to not be initialized, and thread 2 will use the uninitialized context to operate, resulting in a program error.

If the inited variable is decorated with the volatile keyword, this problem does not occur because the context is guaranteed to be initialized when executing to statement 2 o'clock.

Reference: http://www.cnblogs.com/dolphin0520/p/3920373.html

Copyright NOTICE: This article for Bo Master original article, reproduced please indicate the source, view the original article, please visit: Http://blog.csdn.net/xingjiarong

Java Multithreading (vi) in-depth understanding of Volitale keywords

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.