Java 原子类 java.util.concurrent.atomic
Java 原子类 java.util.concurrent.atomic
1、i++为什么是非线程安全的
i++其实是分为3个步骤:获取i的值, 把i+1, 把i+1的结果赋给i
如果多线程执行i++操作,没有同步的话,结果可能不正确
如两个线程同时获取i的值,然后各自+1后,赋给i。正确的情况下i的值应该是加了2,但这里其实加了1而且,前面的结果被覆盖了。
通常做法:synchronized (synchronized方法,synchronized变量), 但这样做效率不是最优的。
2、AtomicInteger的实现
主要依靠:1、volatile 保证了变量的可见性,所有线程不缓存volatile变量,需要时都从内存读取,这样能保证所有数据拿到的值都是最新的。
2、compareAndSet(int expect, int update)判断当前值==expect?当前值=update:错误;
这里做了两步操作,判断跟赋值。但因为cpu提供这样指令的支持,所有能保证这个操作时原子的。
- public class AtomicIntegerextends Number
implements java.io.Serializable { - private staticfinal
long serialVersionUID = 6214790243416807050L; - // setup to use Unsafe.compareAndSwapInt for updates
- private staticfinal Unsafe unsafe = Unsafe.getUnsafe();
- private staticfinal
long valueOffset; - static {
- try {
- valueOffset = unsafe.objectFieldOffset
- (AtomicInteger.class.getDeclaredField("value"));
- } catch (Exception ex) {
throw new Error(ex); } - }
- private volatileint value;
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L; // setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset; static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
} private volatile int value;
3、AtomicInteger 中的set(int newValue) lazySet(int newValue)
void set(int newValue)
设置为给定值。 直接修改原始值,也就是i=newValue操作。
void lazySet(int newValue) 最后设置为给定值。
延时设置变量值,这个等价于set()方法,但是由于字段是volatile类型的,因此次字段的修改会比普通字段(非volatile字段)有稍微的性能延时(尽管可以忽略),所以如果不是想立即读取设置的新值,允许在“后台”修改值,那么此方法就很有用。如果还是难以理解,这里就类似于启动一个后台线程如执行修改新值的任务,原线程就不等待修改结果立即返回(这种解释其实是不正确的,但是可以这么理解)。
4、AtomicInteger中compareAndSet(int expect, int update) weakCompareAndSet(int expect, int update)
boolean weakCompareAndSet(int expect, int update)
如果当前值 == 预期值,则以原子方式将该设置为给定的更新值。JSR规范中说:以原子方式读取和有条件地写入变量但不
创建任何 happen-before 排序,因此不提供与除weakCompareAndSet 目标外任何变量以前或后续读取或写入操作有关的任何保证。大意就是说调用weakCompareAndSet时并不能保证不存在happen-before的发生(也就是可能存在指令重排序导致此操作失败)。但是从Java源码来看,其实此方法并没有实现JSR规范的要求,最后效果和compareAndSet是等效的,都调用了unsafe.compareAndSwapInt()完成操作。
- /**
- * Atomically sets the value to the given updated value
- * if the current value {@code ==} the expected value.
- *
- * @param expect the expected value
- * @param update the new value
- * @return true if successful. False return indicates that
- * the actual value was not equal to the expected value.
- */
- public finalboolean compareAndSet(int expect,int
update) { - return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
- }
- /**
- * Atomically sets the value to the given updated value
- * if the current value {@code ==} the expected value.
- *
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
- *
- * @param expect the expected value
- * @param update the new value
- * @return true if successful.
- */
- public finalboolean weakCompareAndSet(int expect,int
update) { - return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
- }
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* @param expect the expected value
* @param update the new value
* @return true if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
} /**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
* and does not provide ordering guarantees, so is only rarely an
* appropriate alternative to {@code compareAndSet}.
*
* @param expect the expected value
* @param update the new value
* @return true if successful.
*/
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
最新文章
- 让你在PC上调试Web App,UC浏览器发布开发者版
- iOS真机运行 Xcode报错(libpng error: CgBI: unhandled critical chunk)问题已解决;
- python爬取数据保存入库
- java byte&;0xFF
- soapUI 时间格式
- Android—LayoutInflater学习笔记
- Entity Framework 实体框架的形成之旅--数据传输模型DTO和实体模型Entity的分离与联合
- #一周五# win10通用平台,无处不在的Xamarin,msbuild开源,MVP卢建晖的Asp.NET 5系列 (视频)
- Java Web基础——Action+Service +Dao三层的功能划分
- javascript --- 只继承于原型
- 接收content-type:multipart/form-data类型的参数
- NPOI高效匯出Excel
- git 401 错误
- nginx和apache的优缺点比较
- 限制TextBox输入,只能输入整数
- CSS自学笔记(7):CSS定位
- JS延时一秒执行
- [国嵌攻略][106][Linux内存管理子系统]
- Paper藐小之处明察秋毫故时有物外之趣
- [TJOI 2010]中位数
热门文章
- kubectl 常用命令一
- python中os模块的常用方法
- redis 会丢数据吗
- Python 学习笔记:根据输入年月区间,返回期间所有的月份
- Matlab高级教程_第二篇:Matlab相见恨晚的模块_02_并行运算-1
- B-树与B+树 两者的区别
- elasticsearch minhash 测试应用
- rsync实战(二)
- VScode安装后的插件安装
- Educational Codeforces Round 64(Unrated for Div.1+Div. 2)