让AtomicLong再飞一会儿

更多文章请移步: deepinmind


我经常听别人说Java的原子类型(java.util.concurrent.atomic)非常快,在高并发的环境下表现很优秀。很多时候,原子类型确实能很高效的完成它们的任务。然而在有些场景下面,原子类型的竞争冲突带来的隐形开销会带来严重的性能问题。我们来看下原子类型是什么实现的,这样设计意味着什么。


所有的原子类型,比如AtomicLong, AtomicBoolean, AtomicReference等等,都是volatile值的一个包装。sun.misc.Unsafe的引入给它们带来了附加功能,它使得这些类型具备了CAS的能力。

CAS(compare-and-swap)本质上是现代CPU提供的一个原子指令,它旨在提供一个安全高效的非阻塞,多线程的数据操作能力。CAS和锁相比的最大优势在于,由于CAS没有仲裁,不会带来内核级别的负载。相反的,编译器发出了lock cmpxchg, lock xadd, lock addq等CPU指令,这是你从JVM层面调用指令的最快方式了。

在大多数情况下,低开销的CAS是锁原语的一个高效的替代品。然而,在竞争的场景下,CAS的开销也会呈指数级增长。

Dave Dice, Danny Hendler和Ilya Mirsky的一份很有意思的<a href="http://arxiv.org/abs/1305.5800" target="_blank">研究报告</a>里证实了这个问题。我强烈推荐你读一下那篇论文,跟这篇文章相比,那篇论文包含的信息量要大得多。

我从这篇论文里整理出了一些概念,并进行了测试。很多Java程序员看了这个结果会觉得很惊讶,因为长久以来对CAS的性能都存在误区。

实现回避竞争控制的代码非常简单。CAS失败后不要直接循环,先等待一小段时间,让别的线程可以尝试更新。

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.LockSupport;
  
public class BackOffAtomicLong {
  
    public static long bk;
  
    private final AtomicLong value = new AtomicLong(0L);
  
    public long get() {
        return value.get();
    }
  
    public long incrementAndGet() {
        for (;;) {
            long current = get();
            long next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
    }
  
    public boolean compareAndSet(final long current, final long next) {
        if (value.compareAndSet(current, next)) {
            return true;
        } else {
            LockSupport.parkNanos(1L);
            return false;
        }
    }
  
    public void set(final long l) {
        value.set(l);
    }
  
}


测试是在64位的Linux 3.5.0(x86_64)上执行的,CPU是Intel(R) Core(TM) i7-3632QM 2.20GHz(8核),Java版本为64位1.7.0_25-b15。

和预料中一样,读竞争高的情况下,两个实现性能没有太大差别:



然而,写竞争激烈的话结果就很有意思了。这个场景暴露了Hotspot的AtomicLong的乐观重试机制的缺陷。





类似的,读写竞争都很高的时候,这个轻量级访问控制的好处也同样明显。




如果涉及到socket间通信的话,结果会大不相同。不过很不幸,这里丢了些英特尔Xeon平台的测试数据。如果你们有兴趣的话,可以把不同平台的结果发上来。



更多文章请移步: deepinmind






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值