From 0b6de71ecfdf91552f16248ef514936df6434b68 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 15 Mar 2020 14:20:39 +0800 Subject: [PATCH] week_02-76 --- second/week_02/76/AtomicInteger.md | 107 +++++++++++++++++ second/week_02/76/Unsafe.md | 178 +++++++++++++++++++++++++++++ 2 files changed, 285 insertions(+) create mode 100644 second/week_02/76/AtomicInteger.md create mode 100644 second/week_02/76/Unsafe.md diff --git a/second/week_02/76/AtomicInteger.md b/second/week_02/76/AtomicInteger.md new file mode 100644 index 0000000..68859bf --- /dev/null +++ b/second/week_02/76/AtomicInteger.md @@ -0,0 +1,107 @@ + +### 源码解析 + +### 初始化 + +```java +// 拿到Unsafe实例 +private static final Unsafe unsafe = Unsafe.getUnsafe(); +private static final long valueOffset;//变量value的内存偏移量 +//通过unsafe获取AtomicInteger类下value字段的内存偏移量 +static { + try { + valueOffset = unsafe.objectFieldOffset + (AtomicInteger.class.getDeclaredField("value")); + } catch (Exception ex) { throw new Error(ex); } +} + +private volatile int value;// volatile修饰的变量value 保证内存可见、防止指令重排 +``` + +### 构造函数 + +```java +// value=initialValue +public AtomicInteger(int initialValue) { + value = initialValue; +} + +//无参构造默认value=0 +public AtomicInteger() { +} +``` + + + ++ set() get() + +```java +// 返回value +public final int get() { + return value; +} + +// 将传入的值替换value +public final void set(int newValue) { + value = newValue; +} +``` + +```java +//最终把值设置为newValue,使用该方法后,其他线程在一段时间内还会获取到旧值 +public final void lazySet(int newValue) { + unsafe.putOrderedInt(this, valueOffset, newValue); +} +//设置为newValue 并返回旧值 +public final int getAndSet(int newValue) { + return unsafe.getAndSetInt(this, valueOffset, newValue); +} +``` + +```java +//jdk1.8时这两个方法底层调用的是同一个方法 所以认为并无区别 查阅资料到了1.9 weakCompareAndSet才有特殊实现 +//如果调用此方法对象的值等于expect,则设置值为update并返回true;反之不修改返回false +public final boolean compareAndSet(int expect, int update) { + return unsafe.compareAndSwapInt(this, valueOffset, expect, update); +} + +public final boolean weakCompareAndSet(int expect, int update) { + return unsafe.compareAndSwapInt(this, valueOffset, expect, update); +} +``` + +```java +// 返回原值并将当前对象的value+1 +public final int getAndIncrement() { + return unsafe.getAndAddInt(this, valueOffset, 1); + } +// 返回原值并将当前对象的value+ -1 + public final int getAndDecrement() { + return unsafe.getAndAddInt(this, valueOffset, -1); + } + + // 返回原值并将当前对象的value+delta + public final int getAndAdd(int delta) { + return unsafe.getAndAddInt(this, valueOffset, delta); + } + + // 将当前对象的value+1 并返回计算后的结果 + public final int incrementAndGet() { + return unsafe.getAndAddInt(this, valueOffset, 1) + 1; + } +// 将当前对象的value+-1 并返回计算后的结果 + public final int decrementAndGet() { + return unsafe.getAndAddInt(this, valueOffset, -1) - 1; + } + + // 将当前对象的value+delta 并返回计算后的结果 + public final int addAndGet(int delta) { + return unsafe.getAndAddInt(this, valueOffset, delta) + delta; + } + + + + + + +``` \ No newline at end of file diff --git a/second/week_02/76/Unsafe.md b/second/week_02/76/Unsafe.md new file mode 100644 index 0000000..3662870 --- /dev/null +++ b/second/week_02/76/Unsafe.md @@ -0,0 +1,178 @@ + +原子类最核心的模块,很多类都是基于Unsafe里面来实现的 + +####本地方法 +##本地静态方法 在静态块中执行 +private static native void registerNatives(); + +####构造函数 +##私有构造方法 不能被实例化 +private Unsafe() { + } + +####主要方法 + +######获取实例的方法 + +##@CallerSensitive堵住漏洞 防止双重反射获取 +@CallerSensitive +public static Unsafe getUnsafe() { + Class var0 = Reflection.getCallerClass(); + if (!VM.isSystemDomainLoader(var0.getClassLoader())) { + ##判断是否是系统的类加载器加载 不是抛出SecurityException异常 + throw new SecurityException("Unsafe"); + } else { + return theUnsafe; + } +} + +#####读写 + +##Object可以为null,var2表示 + public native int getInt(Object var1, long var2); + +public native void putInt(Object var1, long var2, int var4); + +#####读写地址 + +##获取内存地址的值,如果地址是 0 或者不是指向通过 allocateMemory 方法获取的内存块, +##则结果是未知的 +public native byte getByte(long var1); + +public native void putByte(long var1, byte var3); + +#####本地内存 +##分配指定大小的一块本地内存。这块内存不会被初始化,里面的内容通常是没有用处的数据 +##返回的地址不会是0 且内存块是连续的 +public native long allocateMemory(long var1); + +##重新分配一块指定大小的内存,超出老内存块的字节不会被初始化 +##当请求为0 时,返回的本地指针也为0,如果var1为null,方法则和allocateMemory一样 +public native long reallocateMemory(long var1, long var3); +##将给定的内存块所有字节设置成固定的值(通常是0) +##通过前面两个参数确定内存块的基准地址 有点类似于上面的getInt()方法 +##double-register 地址模型 +public native void setMemory(Object var1, long var2, long var4, byte var6); + +##将给定的内存块所有字节设置成固定的值(通常是0) +##直接传过来是var1地址 +##single-register地址模型 +public void setMemory(long var1, long var3, byte var5) { + this.setMemory((Object)null, var1, var3, var5); +} + +##复制一块内存块里面的字节到另外的内存块,double-register 地址模型 +public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7); + +##复制一块内存块里面的字节到另外的内存块,single-register地址模型 +public void copyMemory(long var1, long var3, long var5) { + this.copyMemory((Object)null, var1, (Object)null, var3, var5); +} + +##释放allocateMemory和reallocateMemory的内存,如果var1为null,不做任何处理 +public native void freeMemory(long var1); + +#####获取类的变量 +##返回字段的偏移量 +@Deprecated +public int fieldOffset(Field var1) { +##判断是否为静态方法,两者调用的本地方法不一样 + return Modifier.isStatic(var1.getModifiers()) ? (int)this.staticFieldOffset(var1) : (int)this.objectFieldOffset(var1); +} + +##返回访问静态字段的地址 +@Deprecated +public Object staticFieldBase(Class var1) { +##获取所有的字段 + Field[] var2 = var1.getDeclaredFields(); + + for(int var3 = 0; var3 < var2.length; ++var3) { + //获取静态字段 + if (Modifier.isStatic(var2[var3].getModifiers())) { + return this.staticFieldBase(var2[var3]); + } + } + + return null; +} + +##返回给定字段在该类的偏移量地址 +##对于任何给的字段都返回同一个值,同一个类不同的字段总是不同的值 +public native long staticFieldOffset(Field var1); + +##返回给定字段的字节偏移量 +public native long objectFieldOffset(Field var1); + +##返回给定字段的位置 +public native Object staticFieldBase(Field var1); + +##检查给定的类是否需要初始化 +public native boolean shouldBeInitialized(Class var1); + +##确定给定的类完成初始化 +public native void ensureClassInitialized(Class var1); + +#####**CAS相关 +##如果变量的值为预期值,则更新变量的值,该操作为原子操作,修改成功返回为true + public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5); + +public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5); + +public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6); + +#####**volatile相关 +##对于给定的操作,有volatile语句,其他和getObject一样,为了保证不同线程之间的可见性 + +public native Object getObjectVolatile(Object var1, long var2); + +public native void putObjectVolatile(Object var1, long var2, Object var4); + +public native int getIntVolatile(Object var1, long var2); + +public native void putIntVolatile(Object var1, long var2, int var4); + +public native boolean getBooleanVolatile(Object var1, long var2); + +public native void putBooleanVolatile(Object var1, long var2, boolean var4); + +public native byte getByteVolatile(Object var1, long var2); + +public native void putByteVolatile(Object var1, long var2, byte var4); + +public native short getShortVolatile(Object var1, long var2); + +public native void putShortVolatile(Object var1, long var2, short var4); + +public native char getCharVolatile(Object var1, long var2); + +public native void putCharVolatile(Object var1, long var2, char var4); + +public native long getLongVolatile(Object var1, long var2); + +public native void putLongVolatile(Object var1, long var2, long var4); + +public native float getFloatVolatile(Object var1, long var2); + +public native void putFloatVolatile(Object var1, long var2, float var4); + +public native double getDoubleVolatile(Object var1, long var2); + +public native void putDoubleVolatile(Object var1, long var2, double var4); + +#####线程 + +##释放当前阻塞的线程,该操作为线程不安全,因为不确定线程是否被销毁 +public native void unpark(Object var1); + +##阻塞当前线程,当发生情况时返回:1.调用unpark方法2.线程被中断3.时间过期4.spuriously +public native void park(boolean var1, long var2); + +##获取一段时间内,运行的任务队列分配到可用处理器的平均数(平常说的 CPU 使用率) +public native int getLoadAverage(double[] var1, int var2); + + + + + + + -- Gitee