前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >openJDK之sun.misc.Unsafe类CAS底层实现

openJDK之sun.misc.Unsafe类CAS底层实现

作者头像
克虏伯
发布2019-04-15 10:43:12
9840
发布2019-04-15 10:43:12
举报

注:这篇文章参考了https://www.cnblogs.com/snowater/p/8303698.html,而后自己结合hotspot源码看的

1.sun.misc.Unsafe中CAS方法

在sun.misc.Unsafe中CAS方法如下:

  1. compareAndSwapObject(java.lang.Object arg0, long arg1, java.lang.Object arg2, java.lang.Object arg3);
  2. compareAndSwapInt(java.lang.Object arg0, long arg1, int arg2, int arg3);
  3. compareAndSwapLong(java.lang.Object arg0, long arg1, long arg2, long arg3);

来看下openJDK8的hotspot中,unsafe是如何实现的,链接http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd/src/share/vm/prims/unsafe.cpp

                                                                    图1

List-1

代码语言:javascript
复制
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
  UnsafeWrapper("Unsafe_CompareAndSwapObject");
  oop x = JNIHandles::resolve(x_h);//更新后的值
  oop e = JNIHandles::resolve(e_h);//期望值
  oop p = JNIHandles::resolve(obj);//更新的对象
  HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);//获取偏移地址,可以理解为获取要更新的属性的内存地址
  oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);//调用方法执行CAS操作
  jboolean success  = (res == e);//atomic_compare_exchange_oop的返回值是否等于期望值,如果等于,则success为true
  if (success)
    update_barrier_set((void*)addr, x);//更新memory barrier
  return success;
UNSAFE_END

    atomic_exchange_oop声明在http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd/src/share/vm/oops/oop.hpp中,如下

List-2

代码语言:javascript
复制
  static oop atomic_compare_exchange_oop(oop exchange_value,
                                         volatile HeapWord *dest,
                                         oop compare_value,
                                         bool prebarrier = false);

    实现在http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd/src/share/vm/oops/oop.inline.hpp中,如下List-3所示:

List-3

代码语言:javascript
复制
inline oop oopDesc::atomic_compare_exchange_oop(oop exchange_value,
                                                volatile HeapWord *dest,
                                                oop compare_value,
                                                bool prebarrier) {
  if (UseCompressedOops) {
    if (prebarrier) {
      update_barrier_set_pre((narrowOop*)dest, exchange_value);
    }
    // encode exchange and compare value from oop to T
    narrowOop val = encode_heap_oop(exchange_value);
    narrowOop cmp = encode_heap_oop(compare_value);

    narrowOop old = (narrowOop) Atomic::cmpxchg(val, (narrowOop*)dest, cmp);//核心
    // decode old from T to oop
    return decode_heap_oop(old);
  } else {
    if (prebarrier) {
      update_barrier_set_pre((oop*)dest, exchange_value);
    }
    return (oop)Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value);//核心
  }
}

    如上的List-3所示,核心的CAS调用Atomic::cmpxchg(val, (narrowOop*)dest, cmp)和Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value)。

    cmpxchg的实现是在http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd/src/share/vm/runtime/atomic.cpp中,如下List-4所示

List-4

代码语言:javascript
复制
jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) {
  assert(sizeof(jbyte) == 1, "assumption.");
  uintptr_t dest_addr = (uintptr_t)dest;
  uintptr_t offset = dest_addr % sizeof(jint);
  volatile jint* dest_int = (volatile jint*)(dest_addr - offset);
  jint cur = *dest_int;//对象当前值
  jbyte* cur_as_bytes = (jbyte*)(&cur);
  jint new_val = cur;
  jbyte* new_val_as_bytes = (jbyte*)(&new_val);
  new_val_as_bytes[offset] = exchange_value;
  //这里有个for循环,资料上说“ 比较当前值与期望值,如果相同则更新,不同则直接返回”?
  while (cur_as_bytes[offset] == compare_value) {
    jint res = cmpxchg(new_val, dest_int, cur);
    if (res == cur) break;
    cur = res;
    new_val = cur;
    new_val_as_bytes[offset] = exchange_value;
  }
  return cur_as_bytes[offset];
}

    cmpxchg_ptr的实现由不同的系统而实现不同,以64位linux为例,是在http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018/08/21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.sun.misc.Unsafe中CAS方法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档