Detailed Explanation of Unsafe Magic Class of Concurrent Programming

1. Detailed explanation of unsafe class

Unsafe is a class located in the sun.misc package. It mainly provides methods for performing low-level, unsafe operations, such as direct access to system memory resources, autonomous management of memory resources, etc. These methods are improving Java operating efficiency and enhancing Java The ability to operate the underlying resources of the language has played a big role. However, because the Unsafe class makes the Java language have the ability to manipulate the memory space similar to the C language pointer, this undoubtedly increases the risk of related pointer problems in the program.

Excessive and incorrect use of Unsafe classes in the program will increase the probability of program errors, making the safe language of Java no longer "safe", so the use of Unsafe must be cautious. The Unsafe class is a singleton implementation that provides a static method getUnsafe to obtain an Unsafe instance. It is legal if and only when the class calling the getUnsafe method is loaded by the boot class loader, otherwise a SecurityException is thrown.

2. How to obtain an instance of Unsafe?

1. Starting from the use restrictions of the getUnsafe method, use the Java command line command -Xbootclasspath/a to append the jar package path of the class A that calls the Unsafe related methods to the default bootstrap path, so that A is loaded by the boot class loader, thereby Obtain the Unsafe instance safely through the Unsafe.getUnsafe method.

java Xbootclasspath/a:${path} //where path is the path of the jar package where the class that calls Unsafe related methods is located

2. Obtain the Unsafe singleton object through reflection.

public class UnsafeInstance {
    public static Unsafe reflectGetUnsafe() {
        try {
    Field field =Unsafe.class.getDeclaredField("theUnsafe"); 
            field.setAccessible(true);
            return (Unsafe) field.get(null);
        } catch (Exception e) {           
            e.printStackTrace(); 
        }return null;  
    }
}

3. Brief introduction of unsafe function (CAS)

3.1 The following code is mainly for CAS related operations

/** *  CAS * @param o         包含要修改field的对象 
* @param offset    对象中某field的偏移量 
* @param expected  期望值 
* @param update    更新值 
* @return          true | false 
*/
public final native boolean compareAndSwapObject(Object var1, longvar2, Object var4, Object var5);
public final native boolean compareAndSwapInt(Object var1, longvar2, int var4, int var5);
public final native boolean compareAndSwapLong(Object var1, longvar2, long var4, long var6);

3.2 The following code is thread scheduling

//取消阻塞线程
public native void unpark(Object thread);
//阻塞线程
public native void park(boolean isAbsolute, long time);
//获得对象锁(可重入锁)
@Deprecated
public native void monitorEnter(Object o);
//释放对象锁
@Deprecated
public native void monitorExit(Object o);
//尝试获取对象锁
@Deprecated
public native boolean tryMonitorEnter(Object o);

The methods park and unpark can realize the suspension and resume of threads. Suspending a thread is realized by the park method. After the park method is called, the thread will be blocked until a timeout or interruption occurs;

Unpark can terminate a suspended thread and restore it to normal.

typical application

The core class AbstractQueuedSynchronizer of the Java lock and synchronizer framework is by calling LockSupport.park() and LockSupport.unpark()

Realize the blocking and wake-up of threads, and the park and unpark methods of LockSupport are actually implemented by calling the park and unpark methods of Unsafe;

3.3, memory barrier

Introduced in Java 8, used to define memory barriers (also known as memory barriers, memory barriers, barrier instructions, etc., is a type of

The synchronization barrier instruction is a synchronization point of the CPU or the compiler in the operation of random access to the memory, so that the point before this point

After all read and write operations are executed, operations after this point can be executed) to avoid code reordering.

//内存屏障,禁止load操作重排序。屏障前的load操作不能被重排序到屏障后,屏障后的load操作不能被重排序到屏障前

public native void loadFence();

//内存屏障,禁止store操作重排序。屏障前的store操作不能被重排序到屏障后,屏障后的store操作不能被重排序到屏障前

public native void storeFence();

//内存屏障,禁止load、store操作重排序

public native void fullFence();

typical application

A new lock mechanism, StampedLock, was introduced in Java 8. It can be seen as an improved version of the read-write lock. StampedLock provides an implementation of an optimistic read lock. This optimistic read lock is similar to a lock-free operation. It does not block the write thread from acquiring the write lock at all, thereby alleviating the "starvation" phenomenon of the write thread when reading more and writing less. Since the optimistic read lock provided by StampedLock does not block the write thread from acquiring the read lock, there will be data inconsistencies when the thread shared variable is loaded from the main memory to the thread working memory. Therefore, when using the optimistic read lock of StampedLock, you need to follow the use case shown in the figure below. The mode used in to ensure data consistency.

 

Guess you like

Origin blog.csdn.net/qq_38130094/article/details/104156504