我是靠谱客的博主 漂亮犀牛,这篇文章主要介绍详解java并发原子类AtomicInteger,现在分享给大家,希望可以做个参考。

详解java并发原子类AtomicInteger

1.1:AtomicInteger是干什么的

​ 多线程修改Interger变量会导致结果不正确,所以设置的一个基于多线程并且基于原子类操作的Integer类,多线程下能够保证线程安全

1.2:AtomicInteger是如何使用的

复制代码
1
2
3
4
5
6
AtomicInteger atomicInteger = new AtomicInteger(1); atomicInteger.addAndGet(2); System.out.println(atomicInteger.get()); atomicInteger.getAndAdd(3); System.out.println(atomicInteger.get());

1.3:AtomicInteger是如何实现的

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private volatile int value; 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); } } public final int addAndGet(int delta) { for (;;) { int current = get(); int next = current + delta; if (compareAndSet(current, next)) return next; } } public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } public final int get() { return value; }

​ addAndget方法内部定义的一个死循环,先通过get()方法得到当前的value值,然后加上2,加完之后使用CAS原子操作让当前值加上2得到3,在并发的过程中,CAS原子操作不一定成功,所以这个定义的for()死循环,成功返回正确的数据,整个过程不会出现多线程处理错误的问题,打个比方,当前线程A得到的current为1,线程B的带的current也为Current1,线程A的next为2,进程CAS操作成功之后就会将value修改为3了,这个时候线程B的next变为3,当线程B进程CAS操作的时候,由于expect是3而不是期望的3了。所以会CAS失败,下一次循环得到的current为3。

​ 这里还有几个注意点

​ 1:get方法回去的value变量时用volatile修饰的,解决的线程的可见性

​ 2:CAS的的实现依赖于CPU提供更多特殊指令,X86CPU提供的cmpxchg指令,在处理器上CAS是一个非常轻量级的操作,其他处理器可能指令不同

​ 3:Unsafe类是一个可以执行不安全、容易犯错的操作的一个特殊类,里面定义了一些native本地方法的类(本地方法在哪里放着)

1.4:Automatic和其它比较存在什么问题

​ 1:CAS导致的ABA问题

​ 2:for循环存在失败重试机制,但是这里隐含的一个假设。线程之间资源竞争是短暂的,大多数情况下,确实大部分重试一次就获得成功,但是凡事都有意外,在有需要的情况下,要考虑下自旋的次数,一面过度消耗CPU

最后

以上就是漂亮犀牛最近收集整理的关于详解java并发原子类AtomicInteger的全部内容,更多相关详解java并发原子类AtomicInteger内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(68)

评论列表共有 0 条评论

立即
投稿
返回
顶部