Unsafe产生于java无法向c那样操作底层操作系统,但一些场景又需要相关操作.所以此类提供了一些java语言对于操作系统内存层面操作的API.这显然被认为是不安全的,所以此类是不公开的,不建议被java应用直接使用.
但现实中已经有大量的java并发相关操作的框架在使用它了....据说此类在计划废弃中.
Unsafe能操作内存?这个是什么概念?都有哪些操作呢?
其实最明显的是它大量方法都是直接操作内存地址进行操作的.方法可以分为下面几类:
我们可以使用LockSupport类进行操作
a. LockSupport.park()对应Unsafe的Unsafe.park(false, 0L)------>给当前所在线程加锁,第一个参数表示true为精度型单位为纳秒,false单位毫秒,第二次参数表示等待时间
b. LockSupport.park.unpark --------->Thread thread对应Unsafe的UNSAFE.unpark(thread)方法(解锁指定线程)
如果,我们直接使用Unsafe,是这样子的:
我们还可以通过Unsafe类获取对象的属性值.因为Unsafe类是直接操作内存的,所以需要我们获得对应的属性内存地址,如下操作:
如下操作,通过unsafe类实现cas原子操作.
好了,上面就是unsafe的基本几种使用,其也是aqs框架中cas操作的基础.下面我们进行aqs相关学习.
AQS研究系列(二)--线程状态和interrupt()、interrupted()、isInterrupted等方法学习
AQS研究系列(三)--AbstractQueuedSynchronizer源码分析
在java中内存中的对象地址是可变的,所以获得的内存地址有可能会变化。要获得内存地址也只能通过Unsafe的方法来获得,如下代码示例:
package com.bijian.study
import java.lang.reflect.Field
import sun.misc.Unsafe
public class Addresser {
//实例化Unsafe 类
private static Unsafe unsafe
static {
try {
//得到field对象
Field field = Unsafe.class.getDeclaredField("theUnsafe")
//设置获取地址
field.setAccessible(true)
unsafe = (Unsafe) field.get(null)
} catch (Exception e) {
e.printStackTrace()
}
}
public static long addressOf(Object o) throws Exception {
Object[] array = new Object[] { o }
long baseOffset = unsafe.arrayBaseOffset(Object[].class)
int addressSize = unsafe.addressSize()
long objectAddress
switch (addressSize) {
case 4:
objectAddress = unsafe.getInt(array, baseOffset)
break
case 8:
objectAddress = unsafe.getLong(array, baseOffset)
break
default:
throw new Error("unsupported address size: " + addressSize)
}
return (objectAddress)
}
//打印地址的长度
public static void main(String... args) throws Exception {
Object mine = "Hi there".toCharArray()
long address = addressOf(mine)
System.out.println("Addess: " + address)
// Verify address works - should see the characters in the array in the output
printBytes(address, 27)
}
//调用此方法得到地址
public static void printBytes(long objectAddress, int num) {
//循环打印得到的地址。
for (long i = 0 i < num i++) {
int cur = unsafe.getByte(objectAddress + i)
System.out.print((char) cur)
}
System.out.println()
}
}
运行结果: