线程安全——JDK Unsafe类使用(内存操作,字段定位与修改等)与CAS原子特性

2022-09-16 13:09:12
java.util.concurrent.atomic包,其中大量的用到Unsafe这个类。那么我们就了解一下
这个类到底是来干嘛的?
由于java不能直接访问操作系统底层,而是通过本地方法来访问。Unsafe类提供了硬件级
别的原子操作,主要提供了以下功能:
内存操作
字段的定位与修改
挂起与恢复
CAS操作(乐观锁)	
字段的定位与修改:
可以定位对象某字段的内存位置也可以修改对象的字段值,即使它是私有的
挂起与恢复
将一个线程进行挂起是通过park方法实现的,调用 park后,线程将一直阻塞直到超时或者
中断等条件出现。
unpark可以终止一个挂起的线程,使其恢复正常。
整个并发框架中对线程的挂起操作被封装在 LockSupport类中,LockSupport类中有各种版
本pack方法,但最终都调用了Unsafe.park()方法
CAS操作(乐观锁)	
首先介绍一下什么是Compare And Swap(CAS)?简单的说就是比较并交换!	
CAS操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B)。
如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理
器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该位置的值。

CAS 有效地说明了:
“我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,
只告诉我这个位置现在的值即可。” 
Java并发包(java.util.concurrent)中大量使用了CAS操作,涉及到并发的地方都调用了
sun.misc.Unsafe类方法进行CAS操作,在Unsafe中是通过compareAndSwapXXX方法实现的。

内存操作:

类中提供的3个本地方法allocateMemory、reallocateMemory、freeMemory分别用于分配内存,扩充内存和释放内存,与C语言中的3个方法对应.

底层方法如下:

package com.bfxy.thread.core.cas;

import java.lang.reflect.Field;
import java.util.Arrays;

import sun.misc.Unsafe;

public class UseUnsafe {

	private static int byteArrayBaseOffset;
	
	public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		
		Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
		theUnsafe.setAccessible(true);
		Unsafe UNSAFE = (Unsafe) theUnsafe.get(null);
		System.err.println(UNSAFE);
		
		byte[] data = new byte[10];
		System.err.println(Arrays.toString(data));
		
		byteArrayBaseOffset = UNSAFE.arrayBaseOffset(byte[].class);
		
		System.err.println("byte[]数组的第一个元素的偏移地址: " + byteArrayBaseOffset);
		
		//设置指定的字节数组, 修改其内存字段的位置:  
		// 1. 在 data 这个数组对象设置 第一个位置 为 1
		UNSAFE.putByte(data, byteArrayBaseOffset, (byte)1);
		// 2. 在 data 这个数组对象设置 第六个位置 为8
		UNSAFE.putByte(data, byteArrayBaseOffset + 6, (byte)8);
		
		System.err.println(Arrays.toString(data));
		
	}
	
}
  • 作者:择业
  • 原文链接:https://blog.csdn.net/qq_39246466/article/details/119568998
    更新时间:2022-09-16 13:09:12