北京啤酒,玫瑰之约电动车,宁明县教育局
本博客系列是学习并发编程过程中的记录总结。由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅。
在java.util.concurrent.atomic
中,普通的原子类型有以下四种:
数组相关的操作类有:
由于上面的原子操作类的实现原理差不多,我们这边就选择atomicinteger
来分析。
public class atomicinteger extends number implements java.io.serializable { private static final long serialversionuid = 6214790243416807050l; //unsafe类提供底层的cas机制 private static final unsafe unsafe = unsafe.getunsafe(); //valueoffset是value值的内存地址值偏移值,这个值的作用是获取value在主内存中的值 private static final long valueoffset; //类加载的时候获取valueoffset的值 static { try { valueoffset = unsafe.objectfieldoffset (atomicinteger.class.getdeclaredfield("value")); } catch (exception ex) { throw new error(ex); } } //atomicinteger具体的值存放在这个变量中, //这个变量使用volatile修饰,具有可见性 private volatile int value; public atomicinteger(int initialvalue) { value = initialvalue; } //默认为0 public atomicinteger() { } }
//value使用volatile修饰,每次能拿到最新值 public final int get() { return value; } //value使用volatile修饰,赋值操作具有原子性,所以这个操作也是线程安全的 //这个方法和compareandset方法的区别是:compareandset方法会判断预期值和当前值,而set方法不会做任何判断,直接更新 // set方法不会在意原始值是多少,而compareandset会确保主内存中的值和预期值相等才更新。 public final void set(int newvalue) { value = newvalue; } //这个方法可能比较令人疑惑,我查了下unsafe的putorderedint方法,如下 /** sets the value of the integer field at the specified offset in the * supplied object to the given value. this is an ordered or lazy * version of <code>putintvolatile(object,long,int)</code>, which * doesn't guarantee the immediate visibility of the change to other * threads. it is only really useful where the integer field is * <code>volatile</code>, and is thus expected to change unexpectedly. */ 上面的意思大致是:putorderedint方法不保证可见性,只有在变量是volatile修饰时才有用, 我们这边的value变量就是用volatile修饰的,所以我认为atomicinteger的`set`方法和`lazyset`方法 功能是一致的。 public final void lazyset(int newvalue) { unsafe.putorderedint(this, valueoffset, newvalue); } //将value设置成给定值,并返回旧值 public final int getandset(int newvalue) { return unsafe.getandsetint(this, valueoffset, newvalue); } //使用cas机制更新 public final boolean compareandset(int expect, int update) { return unsafe.compareandswapint(this, valueoffset, expect, update); } //使用cas机制更新 public final boolean weakcompareandset(int expect, int update) { return unsafe.compareandswapint(this, valueoffset, expect, update); } //cas加1,并且返回原始值 public final int getandincrement() { return unsafe.getandaddint(this, valueoffset, 1); } //cas减1,并且返回原始值 public final int getanddecrement() { return unsafe.getandaddint(this, valueoffset, -1); } //cas加减delta值,并且返回原始值 public final int getandadd(int delta) { return unsafe.getandaddint(this, valueoffset, delta); } //cas加1,并且返回最新值 public final int incrementandget() { return unsafe.getandaddint(this, valueoffset, 1) + 1; } //cas减1,并且返回最新值 public final int decrementandget() { return unsafe.getandaddint(this, valueoffset, -1) - 1; } //cas加减delta值,并且返回最新值 public final int addandget(int delta) { return unsafe.getandaddint(this, valueoffset, delta) + delta; }
下面几个方法个人觉得不是很有用,和上面的区别就是更新的值不是穿进去的,而是通过intunaryoperator
和intbinaryoperator
接口算出来的。
public final int getandupdate(intunaryoperator updatefunction) { int prev, next; do { prev = get(); next = updatefunction.applyasint(prev); } while (!compareandset(prev, next)); return prev; } public final int updateandget(intunaryoperator updatefunction) { int prev, next; do { prev = get(); next = updatefunction.applyasint(prev); } while (!compareandset(prev, next)); return next; } public final int getandaccumulate(int x, intbinaryoperator accumulatorfunction) { int prev, next; do { prev = get(); next = accumulatorfunction.applyasint(prev, x); } while (!compareandset(prev, next)); return prev; } public final int accumulateandget(int x,intbinaryoperator accumulatorfunction) { int prev, next; do { prev = get(); next = accumulatorfunction.applyasint(prev, x); } while (!compareandset(prev, next)); return next; }
总体来说,atomicboolean、atomicinteger、atomiclong和atomicreference原理比较简单:使用cas保证原子性,使用volatile保证可见性,最终能保证共享变量操作的线程安全。
atomiclongarray、atomicintarray和atomicreferencearray的实现原理略有不同,是用cas机制配合final机制来实现共享变量操作的线程安全的。感兴趣的同学可以自己分析下,也是比较简单的。
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
浅析我对 String、StringBuilder、StringBuffer 的理解
使用IDEA搭建SSM框架的详细教程(spring + springMVC +MyBatis)
Springboot整合freemarker 404问题解决方案
引入mybatis-plus报 Invalid bound statement错误问题的解决方法
网友评论