diff --git a/week_02/16/AtomicInteger.md b/week_02/16/AtomicInteger.md new file mode 100644 index 0000000000000000000000000000000000000000..8eaac25b0efffba79e58aa65f1508880a50c978e --- /dev/null +++ b/week_02/16/AtomicInteger.md @@ -0,0 +1,39 @@ +#### AtomicInteger 源码分析 + +自增自减操作 + +```java +// 获取自增 +public final int getAndIncrement() { + return unsafe.getAndAddInt(this, valueOffset, 1); +} +// 自增获取 +public final int incrementAndGet() { + return unsafe.getAndAddInt(this, valueOffset, 1) + 1; +} +// 获取自减 +public final int getAndDecrement() { + return unsafe.getAndAddInt(this, valueOffset, -1); +} +// 自减获取 +public final int decrementAndGet() { + return unsafe.getAndAddInt(this, valueOffset, -1) - 1; +} +``` + + + +cas自旋操作 + +```java +public final int getAndAddInt(Object var1, long var2, int var4) { + int var5; + do { + var5 = this.getIntVolatile(var1, var2); + } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); + + return var5; +} + +``` + diff --git a/week_02/16/unsafe.md b/week_02/16/unsafe.md new file mode 100644 index 0000000000000000000000000000000000000000..b9465954b5ae3748e3290f0031f292a3bca21c32 --- /dev/null +++ b/week_02/16/unsafe.md @@ -0,0 +1,100 @@ +#### Unsafe 源码分析 + +数组 + +```java +// 返回数组中第一个元素的偏移地址 +public native int arrayBaseOffset(Class var1); +// 返回数组中一个元素占用的大小 +public native int arrayIndexScale(Class var1); + +// 1. first index 偏移量 +private static final int base = unsafe.arrayBaseOffset(int[].class); +// 2. scale = 4; +int scale = unsafe.arrayIndexScale(int[].class); +// 3. 计算 scale 二进制后面有几个0,如scale = 4(0100),shift = 2 +shift = 31 - Integer.numberOfLeadingZeros(scale); +// 4. 根据index对scale进行乘法运算获取偏移量 offset,如index = 1,offset = 4(1 << 2) + 16 = 20 +offset = index << shift + base; +// 5. 通过 offset 原子的获取对应的值 +unsafe.getIntVolatile(array, offset); +``` + + + +多线程 + +```java +// 获取系统指针的大小, 64 位是8 +public native int addressSize(); +// 获取内存页大小,2的幂次方,我本机测试是4096 +public native int pageSize(); + +// 取消阻塞 +public native void unpark(Object var1); +// 阻塞直到超时或中断等条件 +public native void park(boolean var1, long var2); +// 弃用,获取对象锁 +public native void monitorEnter(Object var1); +// 弃用,释放对象锁 +public native void monitorExit(Object var1); +// 弃用,尝试获取对象锁 +public native boolean tryMonitorEnter(Object var1); +``` + +内存 + +```java +// 内存分配,相当于c++的os::malloc +public native long allocateMemory(long var1); +// 扩容内存 +public native long reallocateMemory(long var1, long var3); +// 给定的内存块中设置值 +public native void setMemory(Object var1, long var2, long var4, byte var6); +// 内存拷贝 +public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7); +// 释放内存,相当于c++的os::free +public native void freeMemory(long var1); +// 获取给定地址的XX类型的值 +public native byte getXx(long var1); +// 为给定地址设置XX类型的值 +public native void putXx(long var1, xx var3); +``` + +cas + +// 根据第二个参数”偏移量”去拿偏移量这么多的属性的值和第三个参数对比,如果相同则将该属性值替换为第四个参数。该偏移量是指某个字段相对Java对象的起始位置的偏移量,可以通过unsafe.objectFieldOffset(param)去获取对应属性的偏移量。 + +```java +`public final native boolean compareAndSwapXx(Object var1, long var2, Xx var4, Xx var5); +``` + +类-class&object + +```java + +// 获取静态字段的内存地址偏移量 +public native long staticFieldOffset(Field var1); +// 获取一个静态类中给定字段的对象指针 +public native Object staticFieldBase(Field var1); +// 判断是否需要初始化一个类,因为有可能类还没初始化却去获取静态属性 +public native boolean shouldBeInitialized(Class var1); +// 检测类是否已经初始化 +public native void ensureClassInitialized(Class var1); +// 定义一个类 +public native Class defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6); +// 定义一个匿名类 +public native Class defineAnonymousClass(Class var1, byte[] var2, Object[] var3); + +// 返回对象某个属性相对对象内存地址的偏移量 +public native long objectFieldOffset(Field var1); +// 从对象的指定偏移量处获取变量的引用,使用volatile的加载语义 +public native Object getObjectVolatile(Object o, long offset); +// 存储变量的引用到对象的指定的偏移量处,使用volatile的存储语义 +public native void putObjectVolatile(Object o, long offset, Object x); +// 有序、延迟版本的putObjectVolatile方法,不保证值的改变被其他线程立即看到。只有在field被volatile修饰符修饰时有效 +public native void putOrderedObject(Object o, long offset, Object x); +// 绕过构造方法、初始化代码来创建对象 +public native Object allocateInstance(Class cls) throws InstantiationException; +``` +