Java提供了对CAS的支持。参考另一篇文章:https://lobin.iteye.com/blog/2325737
在JAVA中,Unsafe类针对CAS操作提供了3个方法:compareAndSwapInt、compareAndSwapLong、compareAndSwapObject,分别用于原子操作更新Java变量,第1个用于int类型,第2个用于long类型,第3个用于Object类型。这3个方法都是native方法。对应的本机实现分别为Unsafe_CompareAndSwapInt、Unsafe_CompareAndSwapLong、Unsafe_CompareAndSwapObject。参考hotspot\src\share\vm\prims\unsafe.cpp。
compareAndSwapInt方法定义如下:
/** * Atomically update Java variable to <tt>x</tt> if it is currently * holding <tt>expected</tt>. * @return <tt>true</tt> if successful */ public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
compareAndSwapLong方法定义如下:
/** * Atomically update Java variable to <tt>x</tt> if it is currently * holding <tt>expected</tt>. * @return <tt>true</tt> if successful */ public final native boolean compareAndSwapLong(Object o, long offset, long expected, long x);
compareAndSwapObject方法定义如下:
/** * Atomically update Java variable to <tt>x</tt> if it is currently * holding <tt>expected</tt>. * @return <tt>true</tt> if successful */ public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object x);
这3个方法都有4个参数,第1个参数表示要更新的变量所对应的对象,第2个参数表示要更新的变量相对于变量所对应的对象的偏移位置,也就是相对于第1个参数的偏移位置,第3个变量表示期望值,也就是CAS操作中的expect值,第4个参数表示要更新的值,如果更新成功,变量的值更新为要更新的值,返回true,否则返回false。
对应到本机方法实现,方法函数多了两个参数env,unsafe,参考另一篇文章:https://lobin.iteye.com/admin/blogs/2312005.第一个参数是一个JNIEnv类型的指针,表示Java Runtime运行时环境,第2个参数表示Unsafe对象,通过该参数可以得到Unsafe Java对象对应的oop。
其中Unsafe_CompareAndSwapInt方法实现在hotspot\src\share\vm\prims\unsafe.cpp中,代码如下:
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) UnsafeWrapper("Unsafe_CompareAndSwapInt"); oop p = JNIHandles::resolve(obj); jint* addr = (jint *) index_oop_from_field_offset_long(p, offset); return (jint)(Atomic::cmpxchg(x, addr, e)) == e; UNSAFE_END
以上代码需要将宏展开,从代码上看,首先调用resolve函数根据obj(要更新的变量所对应的对象)得到对应的oop,然后调用index_oop_from_field_offset_long函数得到要更新的变量在内存中的地址,最后调用Atomic::cmpxchg函数执行CAS操作更新变量为x,x为要更新的值,e为期望值,在执行CAS操作是会比较实际值和e期望值是否相等,如果相等则更新。
Unsafe_CompareAndSwapLong方法实现在hotspot\src\share\vm\prims\unsafe.cpp中,代码如下:
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) UnsafeWrapper("Unsafe_CompareAndSwapLong"); Handle p (THREAD, JNIHandles::resolve(obj)); jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); if (VM_Version::supports_cx8()) return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; else { jboolean success = false; ObjectLocker ol(p, THREAD); if (*addr == e) { *addr = x; success = true; } return success; } UNSAFE_END
Unsafe_CompareAndSwapLong方法和Unsafe_CompareAndSwapInt方法总体上差不多,这里会检查JVM是否支持cmpxchg8,参考hotspot\src\share\vm\runtime\vm_version.hpp中的以下代码
// does HW support an 8-byte compare-exchange operation? static bool supports_cx8() { return _supports_cx8; }
在hotspot\src\cpu\x86\vm\vm_version_x86.cpp中的VM_Version::get_processor_features方法会检查JVM是否支持cmpxchg8:
void VM_Version::get_processor_features() { ... ... _supports_cx8 = supports_cmpxchg8(); ... ... }
如果支持cmpxchg8的话,调用Atomic::cmpxchg函数执行CAS操作。否则的话就加锁,软件实现CAS操作。
Unsafe_CompareAndSwapObject方法实现在hotspot\src\share\vm\prims\unsafe.cpp中,代码如下:
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); if (UseCompressedOops) { update_barrier_set_pre((narrowOop*)addr, e); } else { update_barrier_set_pre((oop*)addr, e); } oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e); jboolean success = (res == e); if (success) update_barrier_set((void*)addr, x); return success; UNSAFE_END
Unsafe_CompareAndSwapObject方法和上面的两个方法不一样,这里调用的是oopDesc::atomic_compare_exchange_oop函数执行CAS操作更新。
JVM Atomic Atomic::cmpxchg:
CAS操作更新byte类型
参考hotspot\src\share\vm\runtime\atomic.cpp中的代码:
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; 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]; }
CAS操作
通过内嵌汇编的方式通过对应的汇编指令执行CAS操作。
这里定义了一个宏LOCK_IF_MP:
#define LOCK_IF_MP(mp) "cmp $0, " #mp "; je 1f; lock; 1: "
CAS操作更新int类型
参考hotspot\src\os_cpu\linux_x86\vm\atomic_linux_x86.inline.hpp中的代码:
inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { int mp = os::is_MP(); __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)" : "=a" (exchange_value) : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) : "cc", "memory"); return exchange_value; }
这里通过内嵌汇编的方式通过cmpxchgl汇编指令执行CAS操作。内嵌的汇编指令展开后:
__asm__ volatile ("cmp $0, " #%4 "; je 1f; lock; 1: " "cmpxchgl %1,(%3)" : "=a" (exchange_value) : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) : "cc", "memory");
CAS操作更新long类型
参考hotspot\src\os_cpu\linux_x86\vm\atomic_linux_x86.inline.hpp中的代码:
inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { bool mp = os::is_MP(); __asm__ __volatile__ (LOCK_IF_MP(%4) "cmpxchgq %1,(%3)" : "=a" (exchange_value) : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) : "cc", "memory"); return exchange_value; }
这里通过内嵌汇编的方式通过cmpxchgq汇编指令执行CAS操作。内嵌的汇编指令展开后:
__asm__ __volatile__ ("cmp $0, " #%4 "; je 1f; lock; 1: " "cmpxchgq %1,(%3)" : "=a" (exchange_value) : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) : "cc", "memory");
相关推荐
在Java中,`java.util.concurrent.atomic`包下的原子类,如`AtomicInteger`,就是基于CAS实现的。 以`AtomicInteger`的`incrementAndGet()`方法为例,它用于实现无锁的自增操作。在循环中,线程首先获取当前值,...
### Java CAS 原理分析 #### 一、概述 CAS(Compare and Swap)作为一种重要的同步机制,在多线程环境中发挥着关键作用。它能够帮助开发者实现无锁编程,提高程序运行效率。本文将深入剖析Java中CAS的基本原理及其...
2. CAS 操作的实现:JAVA 中的 CAS 操作通过 sun.misc.Unsafe 类的 compareAndSwapInt() 方法实现,该方法借助 JNI 调用 CPU 底层指令来实现 CAS 操作。 3. CAS 操作的应用:JAVA 中的 CAS 操作主要应用于 java.util...
下面我们将详细探讨CAS的核心概念、工作原理以及如何在Java环境中实现和使用CAS。 1. CAS核心概念: - 服务(Service):在CAS术语中,服务是指请求验证的Web应用。当用户尝试访问受保护的资源时,会被重定向到CAS...
Java CAS基本实现原理代码实例解析 Java CAS(Compare And Swap,比较并交换)是 Java 中的一种并发机制,它可以实现原子性的操作。在 Java 中,CAS 是通过 java.util.concurrent.atomic 包来实现的,例如 ...
Java并发机制的底层实现原理涉及到多个方面,包括了本地内存与线程安全的问题、volatile关键字的使用、synchronized关键字的原理以及Java并发在处理器层面是如何实现的。通过这些机制,Java能够有效地管理多线程环境...
CAS(Central Authentication Service)是一款不错的针对 Web 应用的单点登录框架,本文介绍了 CAS 的原理、协议、在 Tomcat 中的配置和使用,研究如何采用 CAS 实现轻量级单点登录解决方案。 CAS 是 Yale 大学发起的...
Java CAS 客户端是Java应用程序与中央认证服务(CAS)进行交互的一种工具,它使得在分布式环境中实现单点登录(Single Sign-On, SSO)成为可能。CAS 是一个开源项目,由耶鲁大学发起,旨在提供一种安全的Web身份验证...
"CAS实现sso单点登录原理" CAS(Central Authentication Service)是Yale大学发起的一个企业级的、开源的项目,旨在为Web应用系统提供一种可靠的单点登录解决方法(属于Web SSO)。CAS开始于2001年,并在2004年12月...
"Java CAS底层实现原理实例详解" Java CAS(Compare And Swap)是一种机制,用于解决多线程并行情况下使用锁造成性能损耗的问题。CAS 的概念是,比较并交换,解决多线程并行情况下使用锁造成性能损耗的一种机制。...
本文将详细介绍CAS的工作原理、实现方式以及在Java中的应用。 CAS操作是Java并发编程中的一项重要技术,它通过无锁的方式提供了线程安全的数据操作。通过理解CAS的工作原理和底层实现,我们可以更有效地使用Java中的...
总的来说,这个项目提供了Java环境下使用Maven构建的CAS SSO解决方案,可以帮助开发者快速搭建一套SSO环境,实现不同应用间的统一登录管理。通过理解服务端和客户端的工作原理以及配置方法,可以灵活地适应各种应用...
3. **集成CAS客户端库**:在外部系统中,需要集成CAS客户端库,如Java CAS Client、Spring Security CAS等,它们负责处理与CAS服务器的交互,包括重定向用户到CAS登录页面、接收和验证服务票证。 4. **配置客户端...
4. **程序源码**:可能包括了一个示例项目,展示了完整的Java LDAP+CAS集成的实现。 5. **群组信息**:提供了一个讨论组的联系方式,供用户交流和寻求帮助。 通过理解和实施这些资源,你可以学习到如何在Java环境中...
对于Java开发者来说,理解和掌握这些组件的工作原理以及如何配置和使用它们,是成功集成CAS的关键。在实际应用中,还应关注性能优化,如调整缓存策略,减少网络延迟,以达到"提速N倍"的效果。此外,由于CAS支持多种...
### CAS原理详解 CAS(Central Authentication Service)是一种开放源代码的单点登录协议和服务实现,广泛应用于企业级应用系统中。其主要目的是提供一个统一的身份验证解决方案,使得用户只需要在一个地方进行登录...
本课程主要通过CAS来实现SSO,本教程会从最基本的基础知识讲起,由浅入深再到实战,完成多应用的单点登录功能。 本课程内容如下: 1、 什么是SSO和CAS 2、 CAS Server服务端和客户端的搭建和配置 3、 单点登录和单...
整合Yale CAS SSO JAVA Client到Java应用中,开发者需要理解CAS的工作原理,包括Ticket Granting Ticket(TGT)和Service Ticket的概念,以及如何在应用程序中配置和调用CAS客户端库。同时,为了保证安全性,需要...