Java concurrency, what is main memory and working memory?

What is main memory, working memory

        These two concepts are proposed in the Java Memory Model. We only need to know that the memory model helps us shield the underlying hardware details. Programmers only need to write code according to its rules, and the written program can be To achieve cross-platform operation, very clever design.

After understanding the memory model, let's go back to the topic. We know that the JVM divides the memory into the following large blocks

  • Heap (shared by all threads in the process)

  • Method area (shared by all threads in the process)

  • Virtual machine stack (independent for each thread)

  • Native local method stack (each thread is independent)

  • pc counter (independent for each thread)

What is the corresponding relationship between main memory and working memory and them? Here comes the conclusion directly.

  • The main memory is the heap + method area

  • The working memory is the virtual machine stack + native local method stack + pc counter

        This knowledge point may seem inconspicuous, but it is very important, because only with this conclusion can it be combined with the actual code examples behind us, otherwise it will feel that the theory is out of touch with the actual operation and cannot be matched.

for example:

There is a Counter counter class, which has a count member variable int type inside, which records the current total, and the specific definition is as follows.

public class Counter {
    private int count;
    public void increment() {
        this.count++;
    }
    public int getCount() {
        return this.count;
    }
}

        Our current task is to call the increment method 100 million times, and then print the number of count, so obviously the correct output should be 100 million.

public static void main(String[] args) {
   // 单线程代码
   Counter counter = new Counter();
   int loopCount = 100000000;
   long startTime = System.currentTimeMillis();
   for (int i = 0; i < loopCount; i++) {
       counter.increment();
   }
   System.out.println("count:" + counter.getCount());  
   System.out.println("take time:" + (System.currentTimeMillis() - startTime) + "ms");
}

// 输出结果
count:100000000
take time:577ms

        We are too familiar with such code, but this time I want to deepen my understanding of how the program works from the specific execution process of the code in the virtual machine stack. First view the bytecode implementation of the increment method of the Counter class through the Javac and Javap commands.

javac Counter.java
javap -verbose Counter.class

// Counter类 increment方法的字节码
  public void increment();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=1, args_size=1
         0: aload_0
         1: dup
         2: getfield      #2                  // Field count:I
         5: iconst_1
         6: iadd
         7: putfield      #2                  // Field count:I
        10: return

        We know that the method call in Java is implemented based on the stack frame, and each stack frame mainly includes the operand stack + the runtime constant pool reference of the class used + the local variable table. I drew a schematic diagram to help you understand the entire execution process, and decomposed the execution steps of the bytecode of one of the count++ operations in the operand stack (taking count=10 as an example), here we should pay attention to the following picture The operation is in the working memory (in the virtual machine stack of the thread where the main method is located).

        ​The process is actually relatively simple. The code we wrote is running like this at the bottom layer. Isn’t it a little bit exciting. Well, here I am going to summarize the methodology! The above code runs correctly in a single thread because the following three conditions are met!

  • The loop is from 0 to 100 million, and it is executed strictly in order (ordering)

  • During the loop, the previous modification to count is visible to the rear (visibility)

  • Because it is executed strictly in order, the count++ operation will not be executed interleaved, so in fact, in a single-threaded environment, it can be considered atomic (atomic)

        As long as one of the above conditions is broken, the execution result may be incorrect, which is why concurrency problems are prone to occur in Java multi-threaded environments, because these three conditions are not met at the same time.

Why does multithreading have concurrency issues?

        As mentioned above, in the instance of the Count class above, we need to satisfy order, visibility, and atomicity at the same time. Among them, orderly and atomicity , we can easily think that because multiple threads are cross-executed, if there is no synchronization Control, orderliness, and atomicity cannot be guaranteed, but what is more difficult to understand here is visibility. The bones are hard to crack first, so next time we will talk about visibility first.

Java learning video

Java basics:

Java300 episodes, Java must-have high-quality videos_Learn Java with hands-on diagrams, making learning a kind of enjoyment

Java project:

[Java game project] 1 hour to teach you how to make classic minesweeper games in Java language_Teach you how to develop games

[Java graduation project] OA office system project actual combat_OA employee management system project_java development

 

Guess you like

Origin blog.csdn.net/java_0000/article/details/125151420