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));
}
}