jdk 源码分析(10)java unsafe 分析
来源:互联网 发布:csgo淘宝买枪 编辑:程序博客网 时间:2024/06/04 20:01
jdk里面原子操作unsafe都是native方法,看不到源代码,所以特意下载openjdk 9 的版本。
1)获取unsafe 对象,这个是openjdk里的方法。通过反射获得。
static {
Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
}
@CallerSensitive
public static Unsafe getUnsafe() {
Class<?> caller = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(caller.getClassLoader()))
throw new SecurityException("Unsafe");
return theUnsafe;
}
所以需要使用时直接
private static final Unsafe unsafe = Unsafe.getUnsafe();
unsafe 对象主要包括1)内存管理
public native long allocateMemory(long var1);public native long reallocateMemory(long var1, long var3);public native void setMemory(Object var1, long var2, long var4, byte var6);
2)对象cas,这个是乐观锁,如果变量没有被其他线程改变的话。会一直尝试去修改变量。直到变成修改值。等会将分析一下源代码。c语言的。
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
这里的参数是,对象,偏移量,期望值,修改值。
获取偏移量的方法:
valueOffset = unsafe.objectFieldOffset (AtomicBoolean.class.getDeclaredField("value"));
还有:
public native long staticFieldOffset(Field var1);public native long objectFieldOffset(Field var1);public native Object staticFieldBase(Field var1);
3)supportlock
public native void unpark(Object var1);public native void park(boolean var1, long var2);
park类似于wait,unpark类似于notify。
4)cas 源码分析
具体见unsafe.cpp (版本: openjdk 9 )
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
oop p = JNIHandles::resolve(obj);
//获取对象的变量的地址
jint* addr = (jint *)index_oop_from_field_offset_long(p, offset);
//调用Atomic操作
return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
} UNSAFE_END
进入atomic.hpp,大意就是先去获取一次结果,如果结果和现在不同,就直接返回,因为有其他人修改了;否则会一直尝试去修改。直到成功。
inline jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest,
jbyte compare_value, cmpxchg_memory_order order) {
STATIC_ASSERT(sizeof(jbyte) == 1);
volatile jint* dest_int =
static_cast<volatile jint*>(align_ptr_down(dest, sizeof(jint)));
size_t offset = pointer_delta(dest, dest_int, 1);
jint cur = *dest_int;
jbyte* cur_as_bytes = reinterpret_cast<jbyte*>(&cur);
// current value may not be what we are looking for, so force it
// to that value so the initial cmpxchg will fail if it is different
cur_as_bytes[offset] = compare_value;
// always execute a real cmpxchg so that we get the required memory
// barriers even on initial failure
do {
// value to swap in matches current value ...
jint new_value = cur;
// ... except for the one jbyte we want to update
reinterpret_cast<jbyte*>(&new_value)[offset] = exchange_value;
jint res = cmpxchg(new_value, dest_int, cur, order);
if (res == cur) break; // success
// at least one jbyte in the jint changed value, so update
// our view of the current jint
cur = res;
// if our jbyte is still as cur we loop and try again
} while (cur_as_bytes[offset] == compare_value);
return cur_as_bytes[offset];
}
unsafe.cpp 里面 还包含很多其他的方法的实现,就不再这里分析了。
阅读全文
0 0
- jdk 源码分析(10)java unsafe 分析
- java unsafe 源码分析详解全面功能
- Unsafe 源码分析
- netty(十四)源码分析之Unsafe
- jdk 源码分析(0) java 源码分析汇总
- jdk 源码分析(14)java ThreadLocal
- jdk 源码分析(9)java ReentrantReadWriteLock分析
- jdk 源码分析(11)java ArrayBlockingQueue 缓存队列分析
- jdk 源码分析(18)java io包分析
- jdk 源码分析(20)java NIO包简单分析
- jdk 源码分析(19)java net包简单分析
- jdk 源码分析(15)java CountDownLatch 源码解析
- jdk 源码分析(16)java CyclicBarrier 源码解析
- netty源码分析 之七 transport(Unsafe)
- jdk 源码分析(1)java hashmap的结构
- jdk 源码分析(4) java Set 结构
- jdk 源码分析(5)java ConcurrentSkipListMap结构
- jdk 源码分析(6)java BitSet结构
- Codeforces 758C Unfair Poll 数学推导,公式
- Spring AspectJ 案例(XML))
- Network Saboteur
- Java入门笔记-(面向对象:封装,多态,继承)
- Codeforces Round #168 (Div. 1) B. Zero Tree(树上DFS)
- jdk 源码分析(10)java unsafe 分析
- Bag of Words(BOW)模型
- 板卡直连笔记本上的VMware
- 两个数的平方和 51Nod
- Linux动态链接库函数加载之GOT与Lazy Binding
- A Plug for UNIX POJ
- hdu 1597 前缀和+lower_bound
- Head First JS阅读笔记之动态数据
- CSS 基础语法有哪些?