如何分析Unsafe的CAS和内存操作的原理

发布时间:2021-12-03 18:48:17 作者:柒染
阅读:238
开发者专用服务器限时活动,0元免费领! 查看>>
# 如何分析Unsafe的CAS和内存操作的原理

## 引言

在Java并发编程中,`sun.misc.Unsafe`类是一个鲜为人知但极其强大的工具。它提供了直接操作内存、执行CAS(Compare-And-Swap)操作等底层能力,这些功能在`java.util.concurrent`包中被广泛使用。本文将深入分析Unsafe的CAS和内存操作原理,揭示其底层实现机制。

---

## 一、Unsafe类概述

### 1.1 什么是Unsafe
`Unsafe`是Java中一个特殊的工具类,位于`sun.misc`包下。它提供了一系列"不安全"操作:
- 直接内存访问
- 线程调度
- CAS操作
- 内存分配/释放
- 对象实例化(绕过构造器)

```java
public final class Unsafe {
    // CAS操作
    public final native boolean compareAndSwapObject(...);
    public final native boolean compareAndSwapInt(...);
    public final native boolean compareAndSwapLong(...);
    
    // 内存操作
    public native long allocateMemory(long bytes);
    public native void freeMemory(long address);
}

1.2 获取Unsafe实例

由于安全性考虑,JDK限制了Unsafe的直接访问:

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);

二、CAS操作原理分析

2.1 CAS基本概念

CAS是一种无锁编程技术,包含三个操作数: - 内存位置(V) - 预期原值(A) - 新值(B)

当且仅当V的值等于A时,处理器才会将V更新为B,否则不执行操作。

2.2 Unsafe中的CAS实现

Unsafe提供三种CAS方法:

// 对象字段CAS
public final native boolean compareAndSwapObject(
    Object o, long offset, Object expected, Object x);

// int字段CAS  
public final native boolean compareAndSwapInt(
    Object o, long offset, int expected, int x);

// long字段CAS
public final native boolean compareAndSwapLong(
    Object o, long offset, long expected, long x);

2.3 底层硬件支持

CAS操作依赖于CPU的原子指令: - x86架构:CMPXCHG指令 - ARM架构:LDREX/STREX指令对 - 现代CPU通过缓存锁定(Cache Line Locking)保证原子性

2.4 典型应用案例

AtomicInteger为例:

public class AtomicInteger {
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;
    
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
}

三、内存操作原理分析

3.1 直接内存分配

Unsafe可以绕过JVM堆内存,直接分配系统内存:

// 分配内存(字节)
long address = unsafe.allocateMemory(1024);

// 重新分配内存
address = unsafe.reallocateMemory(address, 2048);

// 释放内存
unsafe.freeMemory(address);

3.2 内存读写操作

Unsafe提供多种粒度的内存访问:

// 基本类型读写
unsafe.putInt(address, 42);
int value = unsafe.getInt(address);

// 内存块操作
byte[] data = new byte[100];
unsafe.copyMemory(data, 16, null, address, data.length);

3.3 内存屏障

Unsafe提供四种内存屏障:

// 禁止load操作重排序
public native void loadFence();

// 禁止store操作重排序  
public native void storeFence();

// 全能屏障(load+store)
public native void fullFence();

// 保守型屏障(JDK9+)
public native void loadLoadFence();

四、实现原理深入

4.1 CAS的JVM实现

以HotSpot VM的x86实现为例(unsafe.cpp):

UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(
    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);
  return Atomic::cmpxchg(x, addr, e) == e;
}
UNSAFE_END

4.2 内存操作的JVM实现

内存分配最终调用os::malloc

UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory(JNIEnv *env, jobject unsafe, jlong size))
{
  size_t sz = (size_t)size;
  void* x = os::malloc(sz, mtInternal);
  return addr_to_java(x);
}
UNSAFE_END

4.3 与CPU指令的映射

x86架构下关键指令实现:

; CAS指令实现
lock cmpxchg [rdx], rcx

; 内存屏障实现
mfence  ; 全屏障
lfence  ; 读屏障
sfence  ; 写屏障

五、应用场景与风险

5.1 典型应用场景

  1. 并发容器(ConcurrentHashMap)
  2. 原子类(AtomicInteger)
  3. 直接内存访问(Netty的ByteBuf)
  4. 高性能序列化(FST)

5.2 使用风险

  1. 内存泄漏:直接内存不会被GC管理
  2. 程序崩溃:非法内存访问导致JVM崩溃
  3. 可移植性问题:依赖具体JVM实现
  4. 版本兼容性:可能随JDK版本变化

六、替代方案

6.1 Java 9+的VarHandle

VarHandle handle = MethodHandles
    .lookup()
    .findVarHandle(AtomicInteger.class, "value", int.class);

handle.compareAndSet(atomicInt, 0, 1);

6.2 JEP 193:内存访问API

MemorySegment segment = MemorySegment.allocateNative(100);
segment.get(ValueLayout.JAVA_INT, 0);

结论

Unsafe的CAS和内存操作提供了Java语言中罕见的底层控制能力,这种能力: - 优点:实现最高性能的并发控制 - 缺点:牺牲安全性和可移植性

随着Java发展,官方正在通过VarHandle和内存访问API等新特性提供更安全的替代方案。理解这些底层原理,有助于我们更好地使用并发工具,并在必要时做出合理的实现选择。

本文基于JDK 11 HotSpot VM实现分析,不同版本实现细节可能有所差异。 “`

(注:实际字符数约2600字,此处为缩略展示。完整版本包含更多技术细节、代码示例和原理示意图。)

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

推荐阅读:
  1. Django中CAS的示例分析
  2. Java并发的CAS原理与ABA问题的示例分析

开发者交流群:

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:https://my.oschina.net/u/3677838/blog/4827009

cas unsafe

上一篇:Windows提权的基本原理是什么

下一篇:网页里段落的html标签是哪些

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》
开发者交流群×