源码解析 Java 的 compareAndSwapObject 到底比较的是什么?

一、引题

  今天在写一个无锁队列的小项目时用到了 Java Unsafe 包中的 compareAndSwapObject 方法,也就是比较并交换 Java Object ,对于这个方法以前都仅是停留在使用阶段,对底层源码的探究比较少,所以今天就打开源码探究一下该方法的底层到底是怎样实现的,其方法中的这个比较对于 Java Object 来说到底比较的是什么?

二、源码探究

2.1 Java API

  /***
   * Compares the value of the object field at the specified offset
   * in the supplied object with the given expected value, and updates
   * it if they match.  The operation of this method should be atomic,
   * thus providing an uninterruptible way of updating an object field.
   *
   * @param obj the object containing the field to modify.
   * @param offset the offset of the object field within <code>obj</code>.
   * @param expect the expected value of the field.
   * @param update the new value of the field if it equals <code>expect</code>.
   * @return true if the field was changed.
   */
  public native boolean compareAndSwapObject(Object obj, long offset, Object expect, Object update);

  对于 CAS 系列方法的具体使用方法就不在这里赘述了,我们都知道该方法的作用是原子操作比较并交换两个值,运用的时底层硬件所提供的 CAS 支持,在 Java API 中我们可以看到该方法具有四个参数。

  • obj :包含要修改的字段对象;
  • offset :字段在对象内的偏移量;
  • expect : 字段的期望值;
  • update :如果该字段的值等于字段的期望值,用于更新字段的新值;

  同时我们注意到这是一个本地方法,底层是使用 C++ 来实现的,因此我们直接跟进本地方法中。

2.2 C++ API

// Unsafe.h
virtual jboolean compareAndSwapObject(::java::lang::Object *, jlong, ::java::lang::Object *, ::java::lang::Object *);

// natUnsafe.cc
static inline bool
compareAndSwap (volatile jobject *addr, jobject old, jobject new_val)
{
	jboolean result = false;
	spinlock lock;
  
  	// 如果字段的地址与期望的地址相等则将字段的地址更新
	if ((result = (*addr == old)))
    	*addr = new_val;
	return result;
}

// natUnsafe.cc
jboolean
sun::misc::Unsafe::compareAndSwapObject (jobject obj, jlong offset,
                     jobject expect, jobject update)
{
	// 获取字段地址并转换为字符串
	jobject *addr = (jobject*)((char *) obj + offset);
	// 调用 compareAndSwap 方法进行比较
    return compareAndSwap (addr, expect, update);
}

  底层的实现也比较简单,总结来说:

  • 通过我们传入的字段在对象中的偏移量来获取到字段的地址(对象首地址 + 字段在对象中的偏移量);
  • 然后调用 CompareAndSwap 方法比较字段的地址是否与我们期望的地址相等,如果相等则使用我们传入的新地址更新字段的地址;

三、内容总结

  所以最后我们可以得出结论:compareAndSwapObject 方法其实比较的就是两个 Java Object 的地址,如果相等则将新的地址(Java Object)赋给该字段。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值