JAVA memory model notes (JMM)

JAVA memory model

The notes made here are combined with the java memory model in the JVM

Java memory model in the art of concurrent programming with java

Combine some interview questions

There is a clear difference between the JVM memory area and the JAVA memory model

To distinguish the relationship between them

JMM is a rule, mainly to study the visibility of concurrent multi-threaded memory

It is a process abstraction for cache to read and write access

The purpose is to ensure that the memory should beConsistent memoryof

Insert picture description here

Main memory and working memory

The Java memory model creates a working memory for each thread

But all variables should be stored in the main memory, which is not the memory on the hardware.

But part of the JVM
Insert picture description here

Volatile's memory semantics

Semantics 1 Modifications to Volatile variables are immediately visible to other threads

But calculations using Volatile variablesNotThread-safe

For example, if multithreading increments a volatile variable without locking it, a synchronization error will occur

because

Num ++ is actually composed of 4 bytecode operations. The num at the top of the stack is likely to be increased by other threads.

problem solved:

1. You can use AtomicInteger increment operation is incrementAndGet () method

2.方法synchronized

scenes to be used:

1. The operation result does not depend on the current value, or single-thread changes such as the set get method do not depend on the original value

2. Variables do not require other threads to participate in variable constraints

Semantic 2 Volatile prohibits instruction reordering optimization

volatitle boolean  config = false ;

finishconfig(config);
   
config = true;

while(!config){
    sleep()}

dosomethings()

If config is not a Volatile variable

config may be faster than fhinishconfig

This may cause others to execute before configuration.

Summarize the three characteristics of volatile variables

The reading and writing itself are atomic, the others are not self-increasingAtomicity

The operation of the Volatile variable is visible to all threads, and the cache is forced to refresh Visibility

Volatile variables cannot be reordered to add memory barriers Orderly

Lock memory semantics

The release and acquisition of locks is essentially message notification

When a thread releases a lock, it tells the next to acquire the lock message of the thread.

When a thread acquires a lock, it actually receives a lock message from a thread.

sychronized is essentially similar to locking and lock method

The operations in sychronized are atomic because only one thread executesAtomicity

After the sychronized operation is visible to all threads, unlocking a variable will synchronize the variable to the main memoryVisibility

The code in sychronized cannot be reordered because only one thread is executing Orderly

The implementation of some locks is essentially to modify the Volatile variable for CAS operation to achieve memory consistency

Memory semantics of final fields

final is different from lock and Volatile

Final field access is similar to ordinary variables

But the final field must obey two reordering rules

  1. The writing of the final field in the constructor and the subsequent reference of this object are assigned to a reference variable. This operation cannot be reordered
  2. Reading a reference to a final field for the first time, and subsequently reading this final field, this operation cannot be reordered
// 一个对象
static Ex object;
// 构造函数
public Ex(){
    // i 是 final域
    i=0;
    // j 是普通域
    j=2;
}
// A线程写
public void write(){
    object = new Ex()}
// B 线程读
public void read(){
    Ex obj  = object ;
    int a = obj.i;
    int b = obj.j;
}

Look at the example above

The B thread must read out obj.i, the final field, after the initialization of the constructor.

For obj.j, which is a common field, the initial value is not necessarily read, but may be the default initial value.

The final field guarantees that the value or reference of the object must be properly initialized

The final field guarantees that the reference of the object must be read before the final field of the object is read

happens-before

The antecedent rule is an important principle for judging whether data is competing and whether the thread is safe.

  1. The program sequence is executed in sequence flow within a single thread
  2. Tube lock (monitor lock) unlocks a lock before the lock is locked
  3. The volatile principle writes the Volatile variable before reading the variable
  4. Thread start principle The thread start method start () is executed before all operations in the thread
  5. Thread termination principle All operations of the thread are executed before the thread termination, such as the Thread.join end method
  6. The principle of thread interruption is that the interrupted () operation of the thread precedes the detection of interrupt events in the interrupted thread
  7. Object finalization principle The construction method of an object precedes its finalize method
  8. Transitivity, A is prior to B, B is prior to C, then A is prior to C

Double check lock DCL

Double check lock referred to as DCL is a very common lazy loading technology

That is, for some objects with large overhead, they are loaded when they are used. Load on demand. Lazy loading

The following is a thread-unsafe initialization object

public class LazyInital {
    class Instatnce{
        
    }
    private static Instatnce instatnce;
    
    public Instatnce getInstatnce(){
        if(instatnce==null)      // Thread A
            instatnce = new Instatnce();  //  Thread B
        return instatnce;
    }
}

A simple change is to add the sychronized logo to the getInstance method.

But this performance is not good

Below is the wrong version of DCL

public Instatnce getInstatnce(){
    if(instatnce==null){
        synchronized (LazyInital.class){
            if(instatnce==null)
                instatnce = new Instatnce();
        }
    }
    return instatnce;
}

This is called double check lock and it looks very comfortable but has big problems

The initialization of java object is divided into 3 parts

  1. memory = allocate () // allocate memory
  2. initclass (memory) // initialize object
  3. instance = memory // point to object

2 and 3 may be reordered.

The last situation may be

Thread A has not initialized the instance. Thread B has already obtained a reference to the object. At this time, it returns an uninitialized object.

Solution

  1. Disallow initialization of objects and reordering of pointed objects

Use Volatile's semantics to
add the Volatile description

  1. The initialization of thread A objects can be reordered, but should not be visible to thread B.

Use class initialization solution, rely on the characteristics of JVM initialization class object lock

public class InstanceFactory {
    static class Instance{

    }
    // instanceHolder类的初始化加锁
    private static class InstanceHolder{
        private static Instance instance = new Instance();
    }
    public static Instance getInstance(){
        return InstanceHolder.instance;
    }
}

The difference between volatile and synchronized

  1. The essence of volatile is to tell jvm that the value of the current variable in the working memory is uncertain, and it must be read from the main memory

    Synchronized locks the current variable, which can only be read by one thread, and other threads block until the lock is released.

  2. Volatile variable level, synchronized method variable

  3. Volatile can only achieve the visibility of variable modifications, and cannot guarantee the atomicity of operations. For example, Volatile's reading and writing are atomic, but Volatile's operations are not necessarily atomic and self-increasing.

  4. Volatile will not block, synchronized will block

  5. volatitle variable will not be optimized, synchronized will be optimized

Published 22 original articles · Likes2 · Visits 881

Guess you like

Origin blog.csdn.net/weixin_41685373/article/details/105085104