The difference between volatile and synchronized

The difference between volatile and synchronized

 

1, volatile is just a simple synchronization of the main memory area

2. There is no order in volatile execution, and dirty reading is inevitable (when the value of its own variable determines the value of this variable, n=n+1, n++, etc. (during self-operation))

3, will synchronize the main memory area

 

 

Used in multithreading, synchronizing variables. In order to improve efficiency, the thread copies a member variable (such as A) (such as B), and the access to A in the thread actually accesses B. Synchronization of A and B is only done for certain actions. So there is a situation where A and B are inconsistent. volatile is used to avoid this situation. Volatile tells the JVM that the variables it modifies do not retain copies, and directly access the main memory (that is, A) 

======================= ==Separation line 1================================== 

Copyright Notice: Please indicate the article in the form of a hyperlink when reprinting Original source and author information and this statement 
http://aleung.blogbus.com/logs/32090434.html 

In the Java memory model, there is main memory, and each thread also has its own memory (such as registers). For performance, a thread keeps a copy of the variable to be accessed in its own memory. In this way, the value of the same variable in the memory of one thread may be inconsistent with the value in the memory of another thread or the value in the main memory at a certain moment. 

A variable declared as volatile means that the variable can be modified by other threads at any time, so it cannot be cached in thread memory. The following example shows the effect of volatile: 

Java code   Favorite code
  1. public class StoppableTask extends Thread {  
  2.   
  3.   private volatile boolean pleaseStop;  
  4.   
  5.   
  6.   public void run() {  
  7.   
  8.     while (!pleaseStop) {  
  9.   
  10.      // do some stuff...  
  11.   
  12.     }  
  13.   
  14.  }  
  15.   
  16.   
  17.   public void tellMeToStop() {  
  18.   
  19.    pleaseStop = true;  
  20.   
  21.   }  
  22.   
  23. }  


If pleaseStop is not declared as volatile, and the thread checks its own copy when executing run, it cannot know in time that other threads have called tellMeToStop() to modify the value of pleaseStop. 

Volatile cannot replace synchronized in general, because volatile cannot guarantee the atomicity of operations, even if it is only i++, it is actually composed of multiple atomic operations: read i; inc; write i, if multiple threads execute i++ at the same time, volatile can only It is guaranteed that the i they operate on is the same piece of memory, but it is still possible to write dirty data. If combined with the atomic wrapper classes added in Java 5, operations such as their increase do not need to be synchronized. 

Reference: 
http://www.javamex.com/tutorials/synchronization_volatile.shtml 
http://www.javamex.com/tutorials/synchronization_volatile_java_5.shtml 
http://www.ibm.com/developerworks/cn/java/j- jtp06197.html 
==========================Separation Line 2==================== ============= 

  I am afraid it is easiest to explain the difference between volatile and synchronized. Volatile is a variable modifier, while synchronized acts on a piece of code or method; see the following three get codes: 

Java code   Favorite code
  1. int i1;               
  2. int geti1() {return i1;}   
  3. volatile int i2;   
  4. int geti2()  
  5. {return i2;}   
  6. int i3;                
  7. synchronized int geti3() {return i3;}   
  8.   geti1()  


Get the value of i1 stored in the current thread. Multiple threads have multiple copies of the i1 variable, and these i1s can be different from each other. In other words, another thread may have changed the value of i1 in its thread, and this value may not be the same as the value of i1 in the current thread. In fact, Java has an idea called the "main" memory area, where the current "exact value" of a variable is stored. Each thread can have its own copy of the variable, and the value of this variable copy can be different from the one stored in the "main" memory area. So there is actually a possibility: the value of i1 in the "main" memory area is 1, the value of i1 in thread 1 is 2, the value of i1 in thread 2 is 3 - this changes them in both thread 1 and thread 2 The respective i1 value, and this change has not yet been passed to the "main" memory area or other threads. 
  And geti2() gets the i2 value of the "main" memory area. Variables decorated with volatile are not allowed to have copies of variables that differ from the "main" memory area. In other words, a variable that is volatile must be synchronized in all threads; any thread that changes its value, all other threads immediately get the same value. Of course, volatile-modified variable accesses consume a little more resources than normal variables, because it is more efficient for a thread to have its own copy of the variable. 
  Now that the volatile keyword has achieved data synchronization between threads, what should be synchronized for? Hehe, there are two differences between them. First, synchronized acquires and releases monitors—a well-known fact that monitors enforce a block of code to be executed by only one thread at a time if two threads use the same object lock. However, synchronized also synchronizes memory: in fact, synchronized synchronizes the entire thread's memory in the "main" memory area. Therefore, the execution of the geti3() method does the following steps: 
1. The thread requests to acquire the lock of the object monitoring this object (assuming it is not locked, otherwise the thread waits until the lock is released) 
2. The data in the thread memory is eliminated, from the "main" Read in the memory area (the Java virtual machine can optimize this step... [I don't know how to express it later, Khan]) 
3. The code block is executed 
4. Any changes to the variable can now be safely written to the "main" memory area (although the geti3() method does not change the variable value) 
5. The thread releases the object lock monitoring the this object 
  so volatile is only in thread memory and "main" memory. "The value of a variable is synchronized between memory, while synchronized synchronizes the value of all variables by locking and unlocking a monitor. Obviously synchronized consumes more resources than volatile. 

==========================Separation line 3======================== ========== 

The volatile keyword believes that readers who understand Java multithreading are well aware of its role. The volatile keyword is used to declare simple type variables, such as int, float, boolean and other data types. If these simple data types are declared volatile, operations on them become atomic. But this has certain limitations. For example, n in the following example is not atomic: 

Java code   Favorite code
  1. package  mythread;  
  2.   
  3. public   class  JoinThread  extends  Thread  
  4. {  
  5.      public   static volatile int  n  =   0 ;  
  6.     public   void  run()  
  7.     {  
  8.          for  ( int  i  =   0 ; i  <   10 ; i ++ )  
  9.              try   
  10.         {  
  11.                 n  =  n  +   1 ;  
  12.                 sleep( 3 );  //  为了使运行结果更随机,延迟3毫秒   
  13.   
  14.             }  
  15.              catch  (Exception e)  
  16.             {  
  17.             }  
  18.     }  
  19.   
  20.      public   static   void  main(String[] args)  throws  Exception  
  21.     {  
  22.   
  23.         Thread threads[]  =   new  Thread[ 100 ];  
  24.          for  ( int  i  =   0 ; i  <  threads.length; i ++ )  
  25.              //  建立100个线程   
  26.             threads[i]  =   new  JoinThread();  
  27.          for  ( int  i  =   0 ; i  <  threads.length; i ++ )  
  28.              //  运行刚才建立的100个线程   
  29.             threads[i].start();  
  30.          for  ( int  i  =   0 ; i  <  threads.length; i ++ )  
  31.              //  100个线程都执行完后继续   
  32.             threads[i].join();  
  33.         System.out.println( " n= "   +  JoinThread.n);  
  34.     }  
  35. }   

    
如果对n的操作是原子级别的,最后输出的结果应该为n=1000,而在执行上面积代码时,很多时侯输出的n都小于1000,这说明n=n+1不是原子级别的操作。原因是声明为volatile的简单变量如果当前值由该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作: 

n  =  n  +   1 ; 
n ++ ; 

      如果要想使这种情况变成原子操作,需要使用synchronized关键字,如上的代码可以改成如下的形式: 

Java代码   Favorite code
  1. package  mythread;  
  2.   
  3. public   class  JoinThread  extends  Thread  
  4. {  
  5.      public   static int  n  =   0 ;  
  6.   
  7.      public static   synchronized   void  inc()  
  8.     {  
  9.         n ++ ;  
  10.     }  
  11.      public   void  run()  
  12.     {  
  13.          for  ( int  i  =   0 ; i  <   10 ; i ++ )  
  14.              try   
  15.             {  
  16.                 inc();  //  n = n + 1 改成了 inc();   
  17.                 sleep( 3 );  //  为了使运行结果更随机,延迟3毫秒   
  18.   
  19.             }  
  20.              catch  (Exception e)  
  21.             {  
  22.             }  
  23.     }  
  24.   
  25.      public   static   void  main(String[] args)  throws  Exception  
  26.     {  
  27.   
  28.         Thread threads[]  =   new  Thread[ 100 ];  
  29.          for  ( int  i  =   0 ; i  <  threads.length; i ++ )  
  30.              // create 100 threads   
  31.             threads[i]  =   new  JoinThread();  
  32.          for  ( int  i  =   0 ; i  <  threads.length; i ++ )  
  33.              // run the 100 threads just created   
  34.             threads[i].start();  
  35.          for  ( int  i  =   0 ; i  <  threads.length; i ++ )  
  36.              // Continue after 100 threads are executed   
  37.             threads[i].join();  
  38.         System.out.println( " n= "   +  JoinThread.n);  
  39.     }  
  40. }   


    The above code changes n=n+1 to inc(), where the inc method uses the synchronized keyword for method synchronization. Therefore, be careful when using the volatile keyword, not as long as simple type variables are modified with volatile, all operations on this variable are the original operations, when the value of the variable is determined by the previous one, such as n=n+1 , n++, etc., the volatile keyword will be invalid. Only when the value of the variable has nothing to do with its previous value, the operation of the variable is atomic. For example, n = m + 1, this is the original level. So be careful when using the volatile key. If you are not sure, you can use synchronized instead of volatile. 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326373706&siteId=291194637