Home >Java >JavaBase >What is the difference between volatile and synchronize?

What is the difference between volatile and synchronize?

青灯夜游
青灯夜游Original
2020-11-19 14:42:335454browse

Difference: 1. Volatile will not cause thread blocking; synchronized may cause thread blocking. 2. Volatile guarantees the visibility of data, but cannot guarantee atomicity; while synchronized can guarantee atomicity and indirectly guarantee visibility.

What is the difference between volatile and synchronize?

Visibility

Visibility: A thread pair After a shared variable is modified, other threads can immediately see (perceive) the modification (change) of the variable.
The Java memory model synchronizes the modified values ​​of variables in the working memory to the main memory, and refreshes the latest values ​​from the main memory to the working memory before reading the variables. This method relies on main memory. to achieve visibility.

Atomicity (atomicity)

Atomicity: An operation cannot be interrupted, either all executions are completed or not executed .
What the Java memory model guarantees is that all operations within the same thread are from top to bottom. However, when multiple threads are running in parallel, the orderliness of their operations cannot be guaranteed.

Orderliness

Orderliness: Observed in this thread, the operations are all in order; if in a When observing another thread in a thread, all operations are out of order.

What the Java memory model guarantees is that all operations within the same thread are from top to bottom. However, when multiple threads are running in parallel, the orderliness of their operations cannot be guaranteed. .
When the computer executes a program, in order to improve performance, the compiler and processor often rearrange the instructions, which are generally divided into the following three types
What is the difference between volatile and synchronize?
Single-threaded environment It ensures that the final execution result of the program is consistent with the result of the code execution
The processor must consider the data dependency between instructions when reordering In a multi-threaded environment, threads execute alternately. Due to the existence of compiler optimization rearrangement, it is uncertain whether the variables used in the two threads can ensure the consistency of the variables used, and the results are unpredictable.
Do what you know how to do in the exam first, and do what you can't do later.

public void mySort(){
int x = 11; //1
int y = 12; //2
x= x+5; // 3
y = x*x;//4
Possible order is 1234 2134 1324, impossible attribute 4 is before 1 and 3,

because of data dependency.

What is the difference between volatile and synchronize?# volatile prohibits instruction reordering.

public class ReSortSeqDemo {
    int a = 0;
    boolean flag = false;
    
    public void method01() {
        a = 1;           // flag = true;
                         // ----线程切换----
        flag = true;     // a = 1;
    }

    public void method02() {
        if (flag) {
            a = a + 3;
            System.out.println("a = " + a);
        }
    }

}
If two threads are executed at the same time, method01 and method02 are reordered if thread 1 executes method01, and then the switched thread 2 executes method02, there will be different results.

Disable instruction sorting

volatile realizes the optimization of disabling instruction reordering, thus avoiding the phenomenon of program disorder in multi-threaded environment

First understand a concept. Memory Barrier, also known as memory barrier, is a CPU instruction. It has two functions:

Guarantee the execution order of specific operations

Ensure a certain The memory visibility of some variables (use this feature to achieve volatile memory visibility)
Since the compiler and every processor can perform instruction reordering optimization, if a Memory Barrier is inserted between instructions, it will tell the compiler and CPU, No instruction can reorder this Memory Barrier instruction, which means that reordering optimization before and after the memory barrier is prohibited by inserting a memory barrier. Another function of the memory barrier is to force the flushing of various CPU cache data, so that any thread on the CPU can read the latest version of these data.

The following is a schematic diagram of the instruction sequence generated after volatile writing inserts the memory barrier under the conservative strategy:


What is the difference between volatile and synchronize? The following is the instruction sequence generated after volatile reading inserts the memory barrier under the conservative strategy Schematic diagram:

What is the difference between volatile and synchronize?

Thread safety guarantee

The synchronization delay between working memory and main memory causes visibility problems

Can be solved using the synchronzied or volatile keywords, which can use variables modified by one thread to be immediately visible to other threads
For visibility problems and ordering problems caused by instruction rearrangement
can be solved using the volatile keyword, Because another function of volatile is to prohibit instruction reordering optimization

volatile

the

variable## it modifies #Do not retain the copy, directly access the main memory .

In the Java memory model, there is main memory, and each thread also has its own memory (such as registers). For performance, a thread keeps a copy of the variables it accesses in its own memory. In this way, there will be situations where the value of the same variable in the memory of one thread may be inconsistent with the value in the memory of another thread or the value in main memory at a certain moment. Declaring a variable as volatile means that the variable can be modified by other threads at any time, so it cannot be cached in thread memory.

Usage scenarios

You can only use volatile variables to replace locks in limited situations. For volatile variables to provide ideal thread safety, the following two conditions must be met at the same time:
1)The write operation to the variable does not depend on the current value.
2) The variable is not included in an invariant with other variables.

volatile is most suitable for situations where one thread writes and multiple threads read.
If there are multiple threads writing concurrently, you still need to use locks or thread-safe containers or atomic variables instead.

synchronized

When it is used to modify a method or a code block , it can ensure At most one thread can execute this code at the same time.

  1. When two concurrent threads access the synchronized(this) synchronization code block in the same object object, only one thread can be executed at a time. Another thread must wait for the current thread to finish executing this code block before it can execute this code block.
  2. However, when a thread accesses a synchronized(this) synchronized code block of object, another thread can still access the non-synchronized(this) synchronized code block in the object.
  3. Particularly critical is that when a thread accesses a synchronized(this) synchronized code block of object, other threads' access to all other synchronized(this) synchronized code blocks in object will be blocked.
  4. When a thread accesses a synchronized(this) synchronized code block of object, it obtains the object lock of this object. As a result, access by other threads to all synchronized code parts of the object object is temporarily blocked .
    What is the difference between volatile and synchronize?
    Shared resources and objects added, deleted, and modified.

Lock

Starting from jdk 5.0, java provides a more powerful thread synchronization mechanism - synchronization is achieved by explicitly defining synchronization lock objects, and synchronization locks are used Lock object acts as.

The java.util.concurrent.Locks.Lock interface is a tool for controlling multiple threads' access to shared resources. Locks provide exclusive access to shared resources. Only one thread can lock the Lock object at a time. The thread should obtain the Lock object before starting to access the shared resources.

The ReentrantLock class implements Lock, which has the same concurrency and memory semantics as synchronized. In achieving thread-safety control, ReentrantLock is more commonly used, and can display locks and release locks.

What is the difference between volatile and synchronize?

The difference

volatile and synchronized

  • volatile is a variable modifier, while synchronized acts on a piece of code or method .

  • volatile just synchronizes the value of a variable between thread memory and "main" memory; while synchronized synchronizes the value of all variables by locking and unlocking a monitor, obviously synchronized is better than volatile consumes more resources.

  • volatile will not cause thread blocking; synchronized may cause thread blocking.

  • volatile guarantees the visibility of data, but cannot guarantee atomicity; while synchronized can guarantee atomicity and indirectly guarantee visibility. , because it will synchronize the data in private memory and public memory.

  • Variables marked volatile will not be optimized by the compiler; variables marked synchronized can be optimized by the compiler.

Thread safety includes two aspects: atomicity and visibility. Java's synchronization mechanism focuses on these two aspects to ensure thread safety.
The keyword volatile is mainly used when multiple threads can detect that instance variables have been modified and can obtain the latest value. That is, when multiple threads read shared variables, they can obtain the latest value.

The keyword volatile prompts the thread to read variables from shared memory each time instead of reading from private memory, thus ensuring the visibility of synchronized data. But please note: if you modify the data in the instance variable

For example: i, that is, i=i 1, then such an operation is not actually an atomic operation, that is, it is not thread-safe. The operation steps of expression i are broken down as follows:
1) Get the value of i from memory.
2) Calculate the value of i;
3) Write the value of i to memory.
If another thread also modifies the value of i when calculating the value in step 2, dirty read data will appear in name at this time. The solution is to use the synchronized keyword. So volatile itself does not deal with the atomicity of data, but forces the reading and writing of data to affect the main memory in a timely manner.

synchronized and Lock

Lock is an explicit lock (manually open and close, don’t forget to turn off the lock), synchronized is an implicit lock, out of scope Automatically release the lock.
Lock only locks code blocks, synchronized can act on code blocks and methods.
Using Lock lock, jvm spends less time scheduling threads and has better performance. And has better scalability (providing more subclasses).
Sequence of use: Lock-> synchronized code block (has entered the method body and allocated corresponding resources) -> synchronized method (outside the method body).

For more programming-related knowledge, please visit: Programming Learning Course! !

The above is the detailed content of What is the difference between volatile and synchronize?. 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