Comparison of synchronized and volatile in Java multi-thread

Source: Internet
Author: User
Tags volatile

Overview

In multi-threaded concurrent processing, it is often necessary to make visibility access to resources and mutually exclusive synchronization operations. Sometimes we may learn from our predecessors that we need to do volatile or synchronized keyword retouching on our resources. However, we do not know the difference between the two, we cannot tell when to use which keyword. In this article, we will discuss this issue.

Copyright notice

Copyright belongs to the author.
Commercial reprint please contact the author for authorization, non-commercial reprint please specify the source.
This article Coding-naga
Published: April 5, 2016
This article link: http://blog.csdn.net/lemon_tree12138/article/details/51062421
Source: CSDN
More content: Classification >> concurrency and multithreading

Introduction to Memory semantic Analysis Happens-before model

If you understand the Happens-before model by its literal meaning, you may think that this is said to be performed before another operation. However, after learning Happens-before, you will not still understand this. The following is the definition of happens-before in the art of Java concurrent programming:

In JMM (Java Memory Model), if the result of one operation needs to be visible to another operation, there must be a happens-before relationship between the two operations. The two actions mentioned here can be either within a thread or between different threads.

Volatile memory semantics

For multithreaded programming, each thread can have a copy of a variable in shared memory, which is still covered later, and is not explained much here. If a variable is modified by the volatile keyword, then the write of the variable in the local memory is flushed to the shared memory, and the reading of the variable is somewhat different, ignoring the copy of his local memory while reading, just reading the data from the shared variable.

Memory semantics of synchronized

We say that synchronized is actually locking the variable. So either read or write is based on the lock operation of this variable. If a variable is modified by the Synchronized keyword, the write to that variable is to flush the local in-memory copy to the shared memory, and the read of the variable is to flush the value in the shared memory to the local memory and read the data from the local memory. Because the variables are locked during the whole process, other threads cannot read and write to the variable. So it can be understood that any operation on this variable is atomic, that is, the thread is safe.

Example demonstration

Some of the above explanations or definitions may be tedious and boring, and not very well understood. Here we cite some examples to illustrate, so more specific and image some.

Volatile visibility test

Runthread.java

 Public  class runthread extends Thread {    Private BooleanIsRunning =true; Public Boolean isrunning() {returnisrunning; } Public void Setrunflag(BooleanFlag) {isrunning = flag; }@Override     Public void Run() {System.out.println ("I ' m come in ...");BooleanFirst =true; while(isrunning) {if(first) {System.out.println ("I ' m in while ..."); First =false; }} System.out.println ("I ll go out."); }}

Myrun.java

public  class  myrun  { public  static  void  main  (string[] args) throws  interruptedexception {RunTh        Read thread = new  runthread ();        Thread.Start ();        Thread.Sleep (100 );        Thread.setrunflag (false );    System.out.println ( "flag is reseted:"  + thread.isrunning ()); }}

For the above example is just a very common multithreaded operation, here we can easily get the runthread thread in the while into the dead loop.
We can see a thread.sleep in the main () method, combined with the Happens-before memory model mentioned earlier, the following Thread.setrunflag (false) Does not happens-before the while in the child thread. In this way, while the isrunning is modified in the main thread, the while in the child thread does not change, so this throws a dead loop in the while.
In this case, the memory model that the thread is working on is like this

Here, you might wonder why there are two "blocks of memory"? This is due to multi-threaded performance considerations. Although the memory allocated by the object and the member variable is in shared memory, it is possible for each thread to have a copy of the object, which is intended to speed up the execution of the program, which is a notable feature of modern multicore processors. As you can see from the memory model above, the Java thread interacts directly with its own working memory (local memory) and the working memory interacts with the shared memory. This creates a non-atomic operation that is dangerous for non-atomic operations in a multithreaded environment in Java. We already know this because it can be broken by asynchronous read and write operations.
Here the working memory is occupied by while, unable to update the main thread to the shared memory isrunning variable modification. So, if we want to break this limit, we can deal with the volatile keyword. The conditional variable of the while is decorated with the volatile keyword, which is isrunning. Modify the Runthread.java code as follows:

privatevolatilebooleantrue;

In this way, volatile modifies the visibility of the isrunning so that the Thread.setrunflag (false) of the main thread happens-before the while in the child thread. Finally, the child thread jumps out of the while loop and the problem is resolved.
Let's look at how volatile changes the visibility of isrunning.

Here, because IsRunning is modified by volatile, when a child thread wants to access the inrunning in working memory, it is forcibly fetched directly from the shared memory. While the isrunning in shared memory has been modified by the main thread, it has been modified to false and the while is broken, so the thread jumps out of the while loop.

Volatile atomicity Test

Volatile does have a number of advantages, but it has a fatal disadvantage, which is that volatile is not an atomic operation. In the case of multithreading, it is still unsafe.
Perhaps, this time you will ask, since volatile guarantees its visibility between threads, then when to modify it, how to modify it, for the other thread is visible, a thread will read a modified value, why still say it is not safe?
Let's go through an example to illustrate it, so it's more figurative. Let's look at the following piece of code:

 Public  class demonoprotected {    StaticClass MyThread extends Thread {Static intCount =0;Private Static void Addcount() { for(inti =0; I < -;            i++) {count++; } System.out.println ("Count ="+ count); }@Override         Public void Run() {addcount (); }    } Public Static void Main(string[] args) {mythread[] threads =Newmythread[ -]; for(inti =0; I < -; i++) {Threads[i] =NewMyThread (); } for(inti =0; I < -;        i++) {Threads[i].start (); }    }}
300300300400......761875189918

This is a straightforward process without any processing. But the result, too, is straightforward. In fact, the results are not surprising, from the time we learn Java, we know that Java multithreading is not secure. is not from the above study, you feel this can be solved by the volatile keyword? Since you say so, let's try it and add the volatile keyword to the count variable, as follows:

public  class  demovolatile  { static  class MyThread extends Thread {static  volatile  int  count = 0        ;    ... ...    } public  static  void  main  (string[] args) {        ... ...    }}
100300400200......985297529652......81548054

I don't know if this result will make you feel an accident. The confusing number of count is a good understanding, and it should happen when multiple threads are modified at the same time. But we can't find a logical maximum of "10000" in the results, which is a bit odd. Because, logically, volatile modifies the visibility of count, it is a modification of the visible thread B to count for thread A. This is not reflected in the results.
We say that volatile does not guarantee thread safety. In the Addcount () method in the above sub-thread, the code is executed in count++. And a code like count++ from the first lesson of learning Java variables, the teacher should emphasize the process of its execution. count++ can be likened to the following process:

int1;count = tmp;

Visible, count++ is not an atomic operation. Any two threads are likely to separate the above code, and security is out of the way.
So, here we know that volatile can change the visibility between variables on the thread, but it doesn't change the synchronization between threads. Synchronous operations require additional operations to ensure that they are not.

Synchronized synchronization test

It says that volatile does not solve the thread's security problem because volatile cannot build atomic operations. And in multithreaded programming has a very convenient synchronous processing, is the Synchronized keyword. Let's look at how synchronized handles multi-threaded synchronization, the code is as follows:

 Public  class demosynchronized {    StaticClass MyThread extends Thread {Static intCount =0;Private synchronized Static void Addcount() { for(inti =0; I < -;            i++) {count++; } System.out.println ("Count ="+ count); }@Override         Public void Run() {addcount (); }    } Public Static void Main(string[] args) {mythread[] threads =Newmythread[ -]; for(inti =0; I < -; i++) {Threads[i] =NewMyThread (); } for(inti =0; I < -;        i++) {Threads[i].start (); }    }}
100200300......9800990010000

By synchronized we can easily get the desired results. The memory model of the Synchronized keyword can be represented in this way:

When a thread accesses a variable that is synchronized modified, it locks the shared memory of the variable, and then the access of other threads to it is mutually exclusive. Synchronized's internal implementation is also a lock concept.

Ref
    • The core technology of Java multithreaded programming
    • The art of Java concurrent programming

Comparison of synchronized and volatile in Java multi-thread

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.