java(十五):concurrent(0)—AtomicInteger,Unsafe,CAS
来源:互联网 发布:Python Max iteritem 编辑:程序博客网 时间:2024/06/05 14:59
因为java在concurrent包中大量的使用到了AtomicInteger,于是打算从AtomicInteger开始对concurrent包的各个类做一番探究。
如果想对int型数据进行原子操作,那么推荐使用AtomicInteger。
当然也可以使用synchronized代码块,但使用AtomicInteger更高效。
如下代码说明了使用AtomicInteger和使用Integer的区别:
static AtomicInteger i = new AtomicInteger(0);public static void main(String[] args) { Runnable[] threads = new Runnable[300]; for(int j=0;j<300;j++){ threads[j] = new Runnable() { public void run() { System.out.println(i.incrementAndGet()); } }; } for(int j=0;j<300;j++){ new Thread(threads[j]).start(); }}
上述的代码最后输出结果中最大为300.
再看下面的代码:
static Integer i = new Integer(0);public static void main(String[] args) { Runnable[] threads = new Runnable[300]; for(int j=0;j<300;j++){ threads[j] = new Runnable() { public void run() { System.out.println(++i); } }; } for(int j=0;j<300;j++){ new Thread(threads[j]).start(); }}
毫无疑问,将AtomicInteger换成Integer后,多线程没有进行同步,因此一般来说最后的结果中不会有300.
查看AtomicInteger的源码发现,其实同步多线程的操作是通过Unsafe对象来实现的。
于是来先来看看Unsafe吧。
Unsafe
Unsafe类提供了硬件级别的原子操作
对于不想细究的人来说,只需要记住一上一点就行了。即Unsafe提供了和操作系统、内存层面的操作,Unsafe类里面包含大量的native方法,其实就是将这些方法封装为Unsafe类,表示这些方法是底层实现的。
CAS
说道Unsafe,最著名的就是CAS操作,即Compare And Swap,比较并交换。
希望大家不要被这个词误导,CAS真的就是这么简单的意思,硬要在深挖一层的话那就是其实现的细节了。CAS使用Unsafe实现,具体来说是调用native方法,最常用的CAS方法如下:
public final class Unsafe { //... public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
var1是比较值所属的对象,var2需要比较的值(但实际是使用地址偏移量来实现的),如果var1对象中偏移量为var2处的值等于var4,那么将该处的值设置为var5并返回true,如果不等于var4则返回false。
简单来说这就是CAS的全部了,作为使用者,记住这些就OK.
park
还包括unpark方法。
Unsafe提供了park方法和unpark方法用于挂起线程和恢复线程
park系列方法关系到锁的实现,具体到锁在讨论。
定位于修改
Unsafe还可以用于定位对象的属性的内存位置,修改属性值。
- 定位属性位置
对于一个类来说,该类的一个对象,其某个属性值相对于该对象的内存空间的位置是固定的,而类Unsafe可以帮我们获取到这个偏移量。 - 定位属性值
有了属性的偏移量,Unsafe还提供了根据对象,偏移量来获取该对象的值的方法。
上述两个功能的方法参考如下:
public final class Unsafe { //获取类中属性的偏移量 public native long objectFieldOffset(Field var1); //获取对象var1内部偏移量为var2的类型为Int的值 public native int getIntVolatile(Object var1, long var2); //修改对象var1内部偏移量为var2的类型为Int的值为var4 public native void putIntVolatile(Object var1, long var2, int var4);
分配与释放内存
Unsafe甚至提供手动操作内存的操作,正如类名一样,这些操作都是不安全的,我们不应该去使用。
贴一份参考资料,讲unsafe的Java中Unsafe类详解
到这里我么简单浏览了一下Unsafe类,也知道了关于CAS的一些操作, 那么AtomicInteger是如何使用Unsafe来实现同步操作的呢?
AtomicInteger
方法实现
正如开头提到的,AtomicInteger正如类名,完成原子性操作,其大部分操作都是使用Unsafe类来实现的。
public class AtomicInteger extends Number implements java.io.Serializable { //定义unsafe对象 private static final Unsafe unsafe = Unsafe.getUnsafe(); //表示value值的偏移量 private static final long valueOffset; //静态方法获取value的偏移量并赋给valueOffset static { try { valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } private volatile int value;
注意AtomicInteger内部的代码,回顾java对象jvm(二):对象加载浅谈
,除了对象头等知识外,还有一点再此做补充:
一个类一旦定义完毕,其内部字段相对于对象的偏移量就固定了。
于是我们就可以使用类而不是对象来获取属性的偏移量了。 valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
然后就调用Unsafe的方法了,如下:
public class AtomicInteger extends Number implements java.io.Serializable { //...属性定义 //典型的CAS操作,如果value==expect,则设置value=update public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } //设置value为newValue,并返回value public final int getAndSet(int newValue) { return unsafe.getAndSetInt(this, valueOffset, newValue); }
AtomicInteger剩下的方法都是诸如自增,自减等操作了。
同步机制
说到底其并未使用常见的synchronized或者锁机制,那AtomicInteger的同步是如何实现的呢?
秘诀就在于CAS。
部分源码如下:
public class AtomicInteger extends Number implements java.io.Serializable { //... //设置value为newValue,并返回value public final int getAndAdd(int delta) { return unsafe.getAndAddInt(this, valueOffset, delta); } //...}public final class Unsafe { //... 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; } //...}
假设有3个线程,同时调用对于同一个AtomicInteger的getAndAdd(1)操作,然后仔细分析上述代码,就会发现,即使中间的过程可能会存在差异,但最后该AtomicInteger一定是3.
参考JAVA 中无锁的线程安全整数 AtomicInteger介绍和使用,java中的CAS
- java(十五):concurrent(0)—AtomicInteger,Unsafe,CAS
- (转载)AtomicInteger和Unsafe分析
- java concurrent-AtomicInteger
- Java 多线程10:CAS 与 AtomicInteger(乐观锁)
- JAVA多线程系列--Unsafe和CAS,Volatile---concurrent包的基石
- JAVA多线程系列--Unsafe和CAS,Volatile---concurrent包的基石
- Java并发编程AtomicInteger&CAS
- java AtomicInteger 源码之CAS
- java.util.concurrent.atomic 并发包下的原子操作类(AtomicBoolean,AtomicInteger,AtomicLong......))
- Java 并发机制(synchronize/Lock/volitale/CAS/AtomicInteger)的使用和实现
- java.util.concurrent.atomic.AtomicInteger(Atomic详解)
- 并发编程工具之九:AtomicInteger (CAS)
- 聊聊高并发(十七)解析java.util.concurrent各个组件(一) 了解sun.misc.Unsafe类
- Java sun.misc.Unsafe 和 CAS
- 聊聊高并发(二十五)解析java.util.concurrent各个组件(七) 理解Semaphore
- java Unsafe.java(一)
- java Unsafe.java(二)
- java int integer java.util.concurrent.atomic.AtomicInteger
- Hdu 6227 Rabbits
- 百度
- springmvc加载jsp
- Fuc和Action的使用
- kubernetes日志采集与解析
- java(十五):concurrent(0)—AtomicInteger,Unsafe,CAS
- win10 x64安装xgboost错误解决
- oracle:时区
- linux入门-python多版本切换
- HDU-2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包)
- JAVA同步之ReentrantLock可中断锁的使用
- Android --- 使用Intent传递对象的方式
- 一些候选题
- 网络图片加载获取