Concepts that may not be known after five years of experience in Java

This article has been planned for a long time, and I haven't been motivated to write it. I came back a little earlier today to summarize a few concepts.

1. Scalar replacement

First, we must understand what a scalar is. The so-called scalar is a quantity that cannot be further decomposed, such as the basic data types and reference types in java. The relative data can continue to be decomposed, which is called the aggregate quantity. Therefore, if you break up an object and restore its member variables to the basic type for access, it is called scalar substitution. The advantage of scalar replacement is that it avoids the allocation of objects on the heap and creates them directly on the stack, which improves operating efficiency.

2. Escape analysis

Escape analysis determines all the places where a pointer can be stored, and whether it can be guaranteed that the life cycle of the pointer is only in the current process or in other threads. Leaving means that he has escaped.

Escape analysis includes:

  1. Global variable assignment escape: variable assignment to global variable;

  2. Method return value escape: variable as the return value of the method;

  3. The instance reference escapes: the variable is used as the input parameter of the method;

  4. Thread escape: Assignment to class variables or instance variables that can be accessed in other threads;

    public String wrapString(String ... paramArr){
          StringBuffer sb = new StringBuffer();
          for (String string : paramArr) {
              sb.append(string+",");
          }
          return sb.toString();
      }

    In the above code, the scope of the stringBuffer variable only exists in the createString method, no escape will occur, and it can be allocated on the stack.

3. Instruction rearrangement

    In order to improve performance during program execution, compilers and processors often reorder instructions. There are 3 types of reordering:

  1. Compiler optimized reordering. The compiler can rearrange the execution order of statements without changing the semantics of a single-threaded program .

  2. Instruction-level parallel reordering. Modern processors use instruction-level parallelism (Instruction-Level Parallelism, ILP) to overlap multiple instructions. If there is no data dependency , the processor can change the execution order of the statements corresponding to the machine instructions.

  3. Reordering of the memory system. Because the processor uses caches and read/write buffers, this makes load and store operations appear to be performed out of order.

    double a = 3.14;   //A
    double b   = 1.0;     //B

    Therefore, in the case of single thread, the order of A and B instructions can be rearranged.

      int a = 0;
      boolean flag = false;
    
      public void writer() {
          a = 1;                   //1
          flag = true;             //2
      }
    
      public void reader() {
          if (flag) {               //3
              int i = a * a;       //4
          }
      }

    In the case of a single thread, a and flag are rearranged, and the execution order is fixed and does not affect the result. In the case of instruction rearrangement, different results may be obtained.

  4. Volidate can prohibit order rearrangement.

4 、 CASE

    Cas is the abbreviation of compare and swap. It is literally to compare and update. Simply put: Take the value V from a certain memory and compare it with the expected value A. If the result of the memory value V and the expected value A is equal, then We update the new value B to the memory. If it is not equal, then repeat the above operation until it succeeds.

    What problem can cas solve? It can solve the problem of multi-threaded concurrency safety. In the past, we used the synchronize keyword for some multi-threaded code to ensure thread safety; now we put cas into a multi-threaded environment and let’s see how it is To solve it, we assume that two threads A and B execute an int value auto-increment code at the same time and obtain the current value at the same time. We also assume that thread B is faster than A by 0.00000001s, so B is executed first. After thread B performs the cas operation, it finds that the current value is consistent with the expected value, and then performs the auto-increment operation. At this time, the value = value + 1; then A starts to execute, and A also performs the cas operation, but at this time the value of value The value it fetched at the time is no longer the same, so this operation failed, re-fetch the value and compare it successfully, and then update the value value, so that the two threads enter, the value value is incremented twice, which meets our expectations.

You can look at the implementation of the AtomicInteger class.

5 、 GcRoot

    In gc, search downwards from the "GC Roots" object. If an object is not connected to the "GC Roots" by any reference chain, it means that the object can be recycled. The garbage collector reclaims objects that are not GC Roots and are no longer referenced by GC Roots.

In the java language, the objects that can be used as GCRoot include the following:

 a. Objects referenced in the java virtual machine stack (local variable table in the stack frame).

 b . Objects referenced by class static properties in the method area.

 c . Objects referenced by constants in the method area.

 d . The reference object of the JNI native method in the native method stack.

 

to sum up:

Some concepts are summarized above, but it is only a brief introduction. Those who are interested can continue to understand in depth.

 

Guess you like

Origin blog.csdn.net/perfect2011/article/details/108288335