java Unsafe类的compareAndSwap方法

前言

compareAndSwap是个原子方法,原理是cas。就是说如果他是xx,那么就改为xxx。

这个是高效,而且是原子的,不用加锁。

也不会因为其他值改了而产生误操作,因为会先判断当前值,符合期望才去改变。

 

测试代码如下:

 1 package com.example.mass_study.test01.anything;
 2 
 3 /**
 4  * @description:
 5  * @author: luguilin
 6  * @date: 2022-04-15 14:44
 7  **/
 8 
 9 import java.lang.reflect.Field;
10 
11 import sun.misc.Unsafe;
12 
13 
14 public class UnsafeTest {
15 
16     private static Unsafe unsafe;
17 
18     static {
19         try {
20             //通过反射获取rt.jar下的Unsafe类
21             Field field = Unsafe.class.getDeclaredField("theUnsafe");
22             field.setAccessible(true);
23             unsafe = (Unsafe) field.get(null);
24         } catch (Exception e) {
25             System.out.println("Get Unsafe instance occur error" + e);
26         }
27     }
28 
29     public static void main(String[] args) throws Exception {
30         Class clazz = Target.class;
31         Field[] fields = clazz.getDeclaredFields();
32         System.out.println("fieldName:fieldOffset");
33         for (Field f : fields) {
34             // 获取属性偏移量,可以通过这个偏移量给属性设置
35             System.out.println(f.getName() + ":" + unsafe.objectFieldOffset(f));
36         }
37         Target target = new Target();
38         Field intFiled = clazz.getDeclaredField("intParam");
39         int a = (Integer) intFiled.get(target);
40         System.out.println("原始值是:" + a);
41         //intParam的字段偏移是12 原始值是3 我们要改为10
42         System.out.println(unsafe.compareAndSwapInt(target, 12, 3, 10));
43         int b = (Integer) intFiled.get(target);
44         System.out.println("改变之后的值是:" + b);
45 
46         //这个时候已经改为10了,所以会返回false
47         System.out.println(unsafe.compareAndSwapInt(target, 12, 3, 10));
48 
49         System.out.println(unsafe.compareAndSwapObject(target, 24, null, "5"));
50     }
51 }
52 
53 class Target {
54     int intParam = 3;
55     long longParam;
56     String strParam;
57     String strParam2;
58 }

 

结果如下:

 1 fieldName:fieldOffset
 2 intParam:12
 3 longParam:16
 4 strParam:24
 5 strParam2:28
 6 原始值是:3
 7 true
 8 改变之后的值是:10
 9 false
10 true

 

 

compareAndSwapInt是通过反射根据字段偏移去修改对象的,可以看到int是4个字节的偏移量,long是8个字节的偏移量,string是4个字节的偏移量 


注意:Unsafe的对象不能直接new,要通过反射去获取。

posted @ 2022-04-15 14:55  r1-12king  阅读(529)  评论(0编辑  收藏  举报