Home  >  Article  >  Java  >  Learning article: About synchronization in Java

Learning article: About synchronization in Java

php是最好的语言
php是最好的语言Original
2018-08-09 16:48:442055browse

In our daily development work, we are more or less exposed to multi-threaded programming or some concurrency issues. With the upgrade of operating systems and system hardware, concurrent programming is increasingly used in our During development, our initial idea of ​​using multi-threading is to make greater use of system resources. However, when we use multi-threading, there will also be some problems. Let's first look at a piece of code.

    private static int i = 0;

    private static void increse(){
        i++;
    }

    public static void main(String[] args) {
    Thread[] threads = new Thread[20];
        for (int i = 0; i < threads.length; i++){
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 10000; j++){
                        increse();
                    }
                }
            });
            threads[i].start();
        }
        
        while (Thread.activeCount() > 1){
            Thread.yield();
        }
        
        System.out.println(i);
    }

First of all, there is no problem if you look at this code, but if it is in a multi-threaded environment, the results of running this code are basically different. Here, 20 threads are started, and then each The thread calls the increse() method to perform an assignment operation on the variable i. The expected output should be 200000, but why is the output different every time? Same? The reason lies in this placei . This is the root cause of concurrency problems. Why does this seemingly simple i have such a problem? Here we simply learn from the java memory model (JMM). First, JMM stipulates that each thread will have a working memory when running, and then the variable i is stored in the main memory. Every time a thread calculates data, it must go to the main memory to obtain the value of the current variable. To put it simply, a thread calculates the variable i and gets the result. , this data has not been refreshed to the main memory. At this time, other threads have obtained the original value. In other words, it is not known whether the data obtained in this thread is the latest. But this is just a brief explanation from the perspective of JMM. This seemingly simple operation of i actually contains three operations to obtain the value of i. i is incremented and then assigned to i. During these operations, other threads will have a lot of time to do many things. Then someone may ask, is it enough to synchronize this i operation? Yes, how to synchronize it?

Some people say that using volatile to modify the variable i is enough? Yes, the volatile keyword in java does provide a synchronization function, but why does modifying it here still have no effect? The reason is that if a variable is modified with volatile, it will only allow other threads to immediately know the value of the current variable. This is called visibility, but it still cannot be solvedi How to deal with these operational problems? Some people have proposed using the keyword synchronized. I have to admit that this keyword is indeed very powerful and can solve this problem. So have we considered this? Why can this problem be solved and how to solve it? Let me briefly explain. First of all, synchronized belongs to the JVM level. Methods or code blocks with this keyword will eventually be interpreted as . monitorenter and monitorexit instructions, both bytecodes explicitly require a reference type parameter to indicate the object to be locked or unlocked, like this:

public synchronized String f(){
    //code
}

synchronized(object){
    //code
}

Seeing this, we should be able to understand why synchronized can solve the problem of the above program, but we should also clarify a concept which is atomicity. In other words, we When dealing with some multi-threaded problems, you should ensure that some operations on shared data are atomic, so as to ensure correctness. After reading this, I believe you also have a general understanding. Let's summarize it. When it comes to threading issues, what points are worth noting, visibility, atomicity, orderliness, these points are to ensure that multi-threading can A correct prerequisite. As for what orderliness is, this involves the reordering of memory instructions, which is not within the scope of discussion. We will discuss it later.

There is another question to point out here, that is, when we deal with multi-threading issues, we must synchronize or lock. This is not certain. There was a joke on the Internet before, that is When we deal with multi-threaded issues, we sometimes find that the code is written as single-threaded. Of course, this is just a joke, but here we can also see whether single-threaded programs do not have these question? The answer is yes, because there is no resource competition problem in a single thread, so there is no need to discuss it again.

So when do we need to use synchronization, and when do we not? Let's take a look at a piece of code

    public String f(String s1, String s2, String s3){
        return s1 + s2 +s3;
    }

This is a method of string splicing. Let's decompile and take a look. How does the JVM do it here?

Related recommendations:

Detailed explanation of Java thread synchronization and synchronization methods

Detailed introduction to Java synchronization block synchronized block use

The above is the detailed content of Learning article: About synchronization in Java. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn