Java multi-threading learning (c) volatile keyword

mind Mapping:
Here Insert Picture Description

A Profile

Let's look at the Wikipedia definition of "volatile keyword" of:

In programming, especially in C, C ++, C # and Java language, the use of variable or object usually has declared volatile keyword and optimization, multi-thread-related special properties. Usually, volatile keyword is used to prevent the (pseudo) compiler can not think of "the code itself is" changing the code (variable / object) is optimized. As in C, when the volatile keyword can be used to alert the defined variables that follow a compiler may change at any time, so the compiled program each time it needs to store or read this variable, the variable will be read directly from the address Access. Without the volatile keyword, the optimizing compiler may read and store, may temporarily use the value in the register, if this variable is updated by the other program, it will appear inconsistencies.

In the C environment, the true definition and scope of the volatile keyword is often misunderstood. Although C ++, C # and Java have retained the volatile keyword in C, but in these volatile programming language usage and semantics are quite different.

Java is "volatile keyword" keyword:

Before JDK1.2, Java memory model implementation always from main memory (ie, shared memory) reading of variables, does not require any special attention. In the current Java memory model, the variables can be stored thread local memory (such as machine registers), rather than directly in the read and write main memory. This modification may result in a thread in the main memory of the value of a variable, while the other thread to continue using its copy of the variable's value in the register, resulting in inconsistent data .

To resolve data inconsistency problem, we need to declare a variable as volatile , which indicates the JVM, this variable is unstable, every time you use it will be read into main memory.

Visibility two volatile keyword

volatile modified member variable each time it is accessed threads are forced to re-read the value of the member variable from main memory (shared memory) in . Also, when members of the variable changes, forcing thread will change the value written back to main memory (shared memory) . So that at any moment, two different threads always see the same value of a member variable , which will ensure the synchronization of data visibility .

RunThread.java

 private boolean isRunning = true;
 int m;
    public boolean isRunning() {
        return isRunning;
    }
    public void setRunning(boolean isRunning) {
        this.isRunning = isRunning;
    }
    @Override
    public void run() {
        System.out.println("进入run了");
        while (isRunning == true) {
            int a=2;
            int b=3;
            int c=a+b;
            m=c;
        }
        System.out.println(m);
        System.out.println("线程被停止了!");
    }
}

Run.java

public class Run {
    public static void main(String[] args) throws InterruptedException {
        RunThread thread = new RunThread();

        thread.start();
        Thread.sleep(1000);
        thread.setRunning(false);

        System.out.println("已经赋值为false");
    }
}

RunThread class isRunning variables without adding the volatile keyword when running the above code will infinite loop , because although isRunning variables are modified but have not been written to main memory , which also led to the thread in the local memory of value has been true, so it led to the creation of an infinite loop.

The solution is simple: with the former isRunning variable volatile keyword can be.

You are not to think that this is over?

nonexistent! ! ! (There is little need to emphasize the following contents have to look at, otherwise you will be very confused when using the volatile keyword, because the books are almost no mention of this issue)

If you put the while loop code plus any statement or sleep a method you will find an infinite loop output will stop, regardless of whether isRunning variable is added on the volatile keyword.

Plus the output statement:

    while (isRunning == true) {
            int a=2;
            int b=3;
            int c=a+b;
            m=c;
            System.out.println(m);
        }

Plus sleep method:

        while (isRunning == true) {
            int a=2;
            int b=3;
            int c=a+b;
            m=c;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

Why is this?

Because: ** JVM will try to ensure the visibility of memory, even if this variable does not add synchronized keyword. ** In other words, as long as CPU time, JVM will try to ensure that updated variable values. This difference is that with the volatile keyword, the visibility of the volatile keyword will force guarantee thread. Not add this keyword, JVM will try to ensure visibility, but if the CPU has been other things in the process, it can not. Code the beginning, has been in a cycle of death, the state has been occupied by the CPU, the CPU time is no time, JVM can not be enforced CPU time points to get the latest variable value. The statement added output or sleep after, CPU is likely to have the time to ensure the visibility of memory, so the while loop can be terminated.

Three volatile keyword can guarantee atomicity it?

"Java Concurrent Programming Art" says this book to ensure that there is no guarantee the increment operator (non-atomic operations) on the book "Java core multi-threaded programming Art" no guarantee.

Personally, I prefer this argument: ** volatile variables can not guarantee atomicity. ** I personally feel "Java Concurrency in art" says the book volatile keyword but do guarantee atomicity increment operator (non-atomic operations) is not guaranteed on this argument is problematic. Just a personal opinion, I hope not to be sprayed. You can see the following test code:

MyThread.java

public class MyThread extends Thread {
    volatile public static int count;

    private static void addCount() {
        for (int i = 0; i < 100; i++) {
            count=i;
        }
        System.out.println("count=" + count);

    }
    @Override
    public void run() {
        addCount();
    }
}

Run.java

public class Run {
    public static void main(String[] args) {
        MyThread[] mythreadArray = new MyThread[100];
        for (int i = 0; i < 100; i++) {
            mythreadArray[i] = new MyThread();
        }

        for (int i = 0; i < 100; i++) {
            mythreadArray[i].start();
        }
    }

}

operation result:

The above "count = i;" is an atomic operation, but most of the results are correct operation result 99, but there are not a result part 99.

Solution:

Use the synchronized keyword lock . (This is just one way, Lock and AtomicInteger atomic classes can be as learned before the synchronized keyword, we use the synchronized keyword)

Modify MyThread.java as follows:

public class MyThread extends Thread {
    public static int count;

    synchronized private static void addCount() {
        for (int i = 0; i < 100; i++) {
            count=i;
        }
        System.out.println("count=" + count);
    }
    @Override
    public void run() {
        addCount();
    }
}

Count so they all run output is 99, so to guarantee the atomicity of the data or to use the synchronized keyword.

Four synchronized keyword and relatively volatile keyword

  • The volatile keyword is thread synchronization lightweight implementation , so volatile performance is certainly better than the synchronized keyword . But the volatile keyword can only be used for variables can be modified method synchronized keyword and code blocks . efficiency has been significantly improved after the synchronized keyword conducted mainly in order to reduce to obtain and release locks bring the performance overhead introduced by biased locking and lightweight locks and other various optimization after JavaSE1.6, the actual development using the synchronized keyword or some more .
  • Multithreaded access to the volatile keyword blocking will not occur, and may block the synchronized keyword occur
  • to ensure the visibility of the volatile keyword data, but can not guarantee the atomicity of data. Both the synchronized keyword can be guaranteed.
  • volatile keyword is used to solve the visibility of variables between multiple threads, and ynchronized key solution is to access resources between multiple threads synchronization.

Reprinted: https://blog.csdn.net/qq_34337272/article/details/79680771

Guess you like

Origin blog.csdn.net/weixin_39940206/article/details/93617259