JDK AtomicInteger 源码分析
来源:互联网 发布:网络大病众筹 编辑:程序博客网 时间:2024/05/17 01:07
@(JDK)[AtomicInteger]
JDK AtomicInteger 源码分析
Unsafe
实例化
Unsafe在创建实例的时候,不能仅仅通过new Unsafe()
或者Unsafe.getUnsafe()
来获取,因为Java会进行安全校验,只有信任的代码,才能够获取实例。
@CallerSensitivepublic static Unsafe getUnsafe() { Class var0 = Reflection.getCallerClass(); if(var0.getClassLoader() != null) { throw new SecurityException("Unsafe"); } else { return theUnsafe; }}
要达到上述对应的ClassLoader为空,只有通过BootStrapLoader来加载才可以。(可以通过bootclasspath
实现)java -Xbootclasspath:/usr/jdk1.7.0/jre/lib/rt.jar:. com.mishadoff.magic.UnsafeClient
Unsafe里面有一个静态变量,theUnsafe,另一种方式就是通过反射来获取该实例。private static final Unsafe theUnsafe;
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");theUnsafe.setAccessible(true);Unsafe unsafe = (Unsafe) theUnsafe.get(null);
避免初始化
可以使用allocateInstance
方法来绕过构造方法的调用。
public class UnsafeDemo { private UnsafeDemo() { throw new IllegalStateException("非法访问"); } public static void main(String[] args) throws Exception { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafe.get(null); System.out.println(unsafe.allocateInstance(UnsafeDemo.class)); }}
并发
可以通过Unsafe. compareAndSwap
方法来实现Lock-free数据结构。使用的时候一般都会采用while循环在等待(Spin Lock),以及volatile来对内存数据变更能及时反应出来,在JDK里面AtomicInteger
等应用到了。
字段的偏移
可以通过unsafe.objectFieldOffset
来获取类的字段偏移,一般可以和Unsafe. compareAndSwap
结合来使用。
如:
valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"))unsafe.compareAndSwapInt(this, valueOffset, expect, update)
AtomicInteger
字段变量
在AtomicInteger里面,主要通过使用CAS和volatile来实现。
public class AtomicInteger extends Number implements java.io.Serializable { private static final Unsafe unsafe = Unsafe.getUnsafe(); // value字段的偏移,用于compareAndSwapInt方法 private static final long valueOffset; // 这里volatile用于在并发的时候变更值,能够及时的反应到其它线程 private volatile int value;}
具体方法
getAndSet
public final int getAndSet(int newValue) { /* 这里就用到了循环来控制,直到成功,类似自旋锁的方式,在冲突不大的情况下,性能会得到比较好的提升,但是同时也会比较耗CPU,因为是在一直在尝试。同时,在冲突比较大的时候,建议还是使用Lock */ for (;;) { int current = get(); if (compareAndSet(current, newValue)) return current; }}
compareAndSet/weakCompareAndSet
这两个方法,和上面的区别在于只会调用一次,那么就需要开发者考虑失败的情况。
public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}
参考资料
Unsafe:
- http://www.docjar.com/html/api/sun/misc/Unsafe.java.html
- http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/
- http://www.javaworld.com/article/2952869/java-platform/understanding-sun-misc-unsafe.html
CAS
- https://en.wikipedia.org/wiki/Test-and-set
- https://en.wikipedia.org/wiki/Volatile_(computer_programming)
- https://en.wikipedia.org/wiki/ABA_problem
- http://ifeve.com/better_atomicinteger/
0 0
- JDK源码分析-AtomicInteger
- JDK源码分析-AtomicInteger
- JDK AtomicInteger 源码分析
- JDK AtomicInteger 源码分析
- AtomicInteger源码分析
- Java AtomicInteger源码分析
- AtomicInteger源码分析
- AtomicInteger源码分析
- AtomicInteger源码分析
- AtomicInteger 源码分析
- AtomicInteger源码分析
- AtomicInteger源码分析
- Java并发-AtomicInteger源码分析
- JDK 源码解析 —— AtomicInteger
- Java并发之AtomicInteger源码分析
- 【Java8源码分析】并发包-AtomicInteger
- AtomicInteger源码
- AtomicInteger源码
- jquery获取复选框的值
- Protobuf-net ProtoGen的使用
- 【HTML】HTML 速查列表
- 微服务
- 基于Dragonboard 410c的家庭智能环保卫士——(3)室内路径规划
- JDK AtomicInteger 源码分析
- AJAX+JQuery+SpringMVC实现图片上传
- 环境配置说明(无CUDA,caffe在CPU下运行)caffe+Ubuntu14.0.4 64bit
- 查看sqlite数据库
- 浅谈 Ljava.lang.Object 异常
- java动态加载jar包,并运行其中的类和方法
- 【工作笔记】ElasticSearch从零开始学(二)—— 入门(搜索)
- 接口测试自动化生成框架
- 如何直接打开android系统的wifi设置页面,防止intent劫持