Alibaba interview will ask volatile, you really will yet

Thank refer to the original -http: //bjbsair.com/2020-03-27/tech-info/7026/
talk about your understanding of the volatile?

Do you know the underlying implementation mechanism volatile do?

volatile variables and atomic variables What is the difference?

volatile usage scenarios, you can give two examples?

Before a relatively detailed introduction to the Java Memory Model --JMM, JMM revolves around how to handle concurrent process visibility, and atomic ordering of these three features built up , and volatile can guarantee that two characteristics which, the following specifically discussed this interview will be asked keywords.

Ali interview will ask volatile, you really will be it?

  1. The concept
    =====

volatile keyword in Java, is a variable modifier is used to modify different threads access and modify variables.


  1. Java Memory Model 3 properties
    ==================

2.1 Visibility

Visibility is a complex property because the visibility of error will always contrary to our intuition. In general, we can not guarantee thread can perform a read operation in a timely manner to see the value of other threads written, and sometimes simply impossible. In order to ensure visibility among multiple threads of memory write operations, you must use the synchronization mechanism.

Visibility means visibility between threads, a thread modifies a state of another thread is visible . That is the result of a modification of the thread. Another thread can immediately see.

In Java volatile, synchronized and final can achieve visibility.

2.2 Atomicity

Atomicity means that when a thread is executing an operation, the middle stopper or can not be split, or the overall success or failure of the whole. For example a = 0; (a non-long and double) This operation is indivisible, then we say that the operation is atomic. Another example: a ++; this operation is actually a = a + 1; is divisible, so he is not an atomic operation. Non-thread-safe atomic operations there will be problems, we need to use synchronous technology (sychronized) to make it into an atomic operation. Operation is atomic, then we call it atomic. Providing some of the atoms of Java classes under concurrent package, AtomicInteger, AtomicLong, AtomicReference like.

In Java and synchronized in lock, unlock operation guarantee atomicity.

2.3 orderliness

Java language provides two keywords volatile and synchronized to ensure orderly, volatile because of its own with "prohibit instruction reordering" of semantics, synchronized operation between threads is by "allowing only one variable at a time in the same thread lock its operation "rule obtained, the rules determine the synchronization holding two blocks of the same object lock can only be executed serially.


  1. volatile is a lightweight synchronization mechanism provided by the Java virtual machine
    =================================
  • Ensure visibility
  • Does not guarantee atomicity
  • Prohibition instruction rearrangement (to ensure orderly)

3.1 empty rumor, code verification

3.1.1 Visibility verification

class MyData {  
    int number = 0;  
    public void add() {  
        this.number = number + 1;  
    }  
}  
  
   // 启动两个线程,一个work线程,一个main线程,work线程修改number值后,查看main线程的number  
   private static void testVolatile() {  
        MyData myData = new MyData();  
       
        new Thread(() -> {  
            System.out.println(Thread.currentThread().getName()+"\t come in");  
            try {  
                TimeUnit.SECONDS.sleep(2);  
                myData.add();  
                System.out.println(Thread.currentThread().getName()+"\t update number value :"+myData.number);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }, "workThread").start();  
  
        //第2个线程,main线程  
        while (myData.number == 0){  
            //main线程还在找0  
        }  
        System.out.println(Thread.currentThread().getName()+"\t mission is over");        
        System.out.println(Thread.currentThread().getName()+"\t mission is over,main get number is:"+myData.number);  
    }  
}

Run testVolatile () method, the following output, you will find an infinite loop in the main thread, the main thread has been explained value is 0

workThread	 execute  
workThread	 update number value :1  
复制代码

Modify volatile int number = 0 ,, plus keyword volatile, re-run before the number, main thread gets 1 results

workThread	 execute  
workThread	 update number value :1  
main	 execute over,main get number is:1

3.1.2 Verification does not guarantee atomicity

class MyData {  
    volatile int number = 0;  
    public void add() {  
        this.number = number + 1;  
    }  
}  
  
private static void testAtomic() throws InterruptedException {  
  MyData myData = new MyData();  
  
  for (int i = 0; i < 10; i++) {  
    new Thread(() ->{  
      for (int j = 0; j < 1000; j++) {  
        myData.addPlusPlus();  
      }  
    },"addPlusThread:"+ i).start();  
  }  
  
  
  //等待上边20个线程结束后(预计5秒肯定结束了),在main线程中获取最后的number  
  TimeUnit.SECONDS.sleep(5);  
  while (Thread.activeCount() > 2){  
    Thread.yield();  
  }  
  System.out.println("final value:"+myData.number);  
}

Run testAtomic found last output value, not necessarily the desired value 10000, 10000 tend to be smaller than the value.

final value:9856

Why is this so, because i ++ conversion to bytecode instruction time is four instructions

  • getfield obtain the original value
  • iconst_1 the value of the stack
  • are incremented iadd
  • putfield the operation after the write-back to main memory iadd

Such competition would exist in a multi-threaded run time, there may be a case of missing write values.

Ali interview will ask volatile, you really will be it?

How to solve the atomic problem?

Or added directly synchronized Automic atoms class.

3.1.3 authentication prohibition instruction rearrangement

When the computer executes the program, in order to improve performance, often have compiler and processor instructions do rearrangement, generally divided into the following three

Ali interview will ask volatile, you really will be it?

Between the processors must be considered when performing the reordering instruction data dependencies , we called as-if-serial semantics

Single-threaded environment to ensure the final implementation of the program consistent with the results of the implementation and results of the code sequence; however multithreaded environment alternately thread execution, because the compiler optimization rearrangement exists, the variables used in the two threads can ensure consistency can not be determined the results can not be predicted.

We tend to use the following code verification volatile prohibit instruction reordering, if multi-threaded environment, `the final output is not necessarily the result of our imagination to 2, then you should both variables are set to volatile.

public class ReSortSeqDemo {  
  
    int a = 0;  
    boolean flag = false;  
  
    public void mehtod1(){  
        a = 1;  
        flag = true;  
    }  
  
    public void method2(){  
        if(flag){  
            a = a +1;  
            System.out.println("reorder value: "+a);  
        }  
    }  
}

volatile achieve a ban on instruction reordering optimization, thus avoiding the phenomenon of order execution procedures in a multithreaded environment.

Another of our most common multi-threaded environment singleton DCL (double-checked locking) version of is to use the characteristics of volatile disable command rearrangement.

public class Singleton {  
  
    private static volatile Singleton instance;  
    
    private Singleton(){}  
    // DCL  
    public static Singleton getInstance(){  
        if(instance ==null){   //第一次检查  
            synchronized (Singleton.class){  
                if(instance == null){   //第二次检查  
                    instance = new Singleton();  
                }  
            }  
        }  
        return instance;  
    }  
}

Because of the presence instruction reordering, double-ended retrieval mechanism is not necessarily thread-safe.

why ?

Because: instance = new Singleton (); procedure to initialize the object is not really an atomic operation, it will perform divided into three parts,

  1. For instance allocate memory
  2. Call the instance constructor to initialize the object
  3. The instance of the object points to memory space allocation (step executing the instance on which the non-null)

Step 2 and 3 data dependency relationship does not exist, the virtual machine if there is an instruction reordering optimization, the order of steps 2 and 3 can not be determined. If thread A and the first to enter the first synchronized block 3 is performed without performing 2, this time instance as has been non-null. This time thread B at the first time check, you will find instance has a non-null, it will return to its use, but this time has not been initialized instance in fact, it will naturally go wrong. So we have to restriction instruction rearrangement object instance, modified with volatile (5 JDK before using a volatile double lock detection is problematic).


  1. Principle
    =====

volatile and can guarantee the visibility of the thread provides a certain orderliness, but can not guarantee atomicity. In the underlying JVM implementation is based on the memory barrier.

  • When the non-volatile read and write variables, the variables each thread memory copy start to the CPU cache. If the computer has multiple CPU, each thread can be processed on a different CPU, which means that each thread can be copied to a different CPU cache in
  • The declaration of a variable is volatile, JVM ensures that each read variables read from memory, CPU cache to skip this step, so there would be no question of the volatile variable visibility when writing, will be added in a write operation store barrier instruction, the working memory of a shared variable refresh back to main memory; volatile variables when read, will add a load barrier instruction after a write operation, read the shared variable from main memory;

Get generated by the JIT compiler hsdis tool assembly instruction to look to the volatile CPU will write to do something, or the top of the single mode of embodiment can be seen

Ali interview will ask volatile, you really will be it?

(PS: the specific assembly instructions for my Javaer south too, but we can know JVM bytecode, putstatic meaning is to set the value of a static variable, then there's putstatic instance, line 17 of code and is more determined is assigned to the instance. Sure enough, as all kinds of information says, and found the lock add1 is said to have read. here you can look at these two www.jianshu.com/p/6ab7c3db1..., www.cnblogs.com/xrq730/ p / 70 ...)

When there will be more shared variables that volatile write a second line of assembler code, the sentence code means add zero to the original value , which before the addition instruction of ADDLs Lock modified. By Charles IA-32 Architectures Software Developer's Manual shows, lock prefix instruction in multi-core processors will lead to two things:

  • The current data processor cache line is written back to system memory
  • The write-back cache memory operation causes the other CPU memory address where the data is invalid

It is realized lock "to prevent instruction reordering" of volatile "memory visible" characteristics


  1. Usage scenarios
    =======

You can only use volatile variables instead of locking in some cases limited. For thread-safe volatile variable is ideal, you must meet the following two conditions:

  • Write to the variable does not depend on the current value
  • This variable is not included in the invariant with other variables

In fact, the need to ensure atomicity scene, do not use volatile.


  1. volatile performance
    ==============

volatile read performance is almost the same consumption of normal variables, but the slower write operation, it is necessary to insert as many memory barrier instruction in native code, to ensure that the processor does not occur out of order execution.

Reference "proper use volaitle variable" a text of the words:

Difficult to make accurate and comprehensive evaluation, such as "X is always faster than Y", especially in terms of the internal operation of the JVM. (For example, in some cases JVM may be able to completely remove the locking mechanism, which makes it difficult to compare the abstract volatile and synchronized overhead.) That is, on most of the current processor architecture, volatile read overhead is very low - and almost non-volatile read operations. The volatile write overhead than non-volatile write a lot more, because to ensure the visibility of the need to implement the defined memory (Memory Fence), even so, total spending remains low volatile than the lock acquisition.

volatile lock operation does not like to cause obstruction, and therefore, in the case of safe use of volatile, volatile lock can provide superior scalable features. If the number of read operations is much more than write, compared with the lock, volatile variables can often reduce the performance overhead of synchronization.

Original articles published 0 · won praise 0 · Views 272

Guess you like

Origin blog.csdn.net/zxjoke/article/details/105139584