比AtomicLong更快的算法

14-01-15 banq
              

一般认为原子类型(java.util.concurrent.atomic类)能充分发挥代码的快速和高并发特点,大部分时间atomic确实发挥了更大作用,不过也有一些场景其实隐藏了非管理竞争的消耗,以至于成为一个严重的性能问题。

首先让我们来看看Atomic是如何实现的?所有的原子类型如AtomicLong, AtomicBoolean , AtomicReference等,基本上都是包装的volatile挥发性的值,这个新增的值来自于内部为这些类型提供CAS功能的sun.misc.Unsafe。

CAS(compare-and-swap)比较并交换)本质上是现代硬件上的实现,允许无堵塞 多线程数据处理能以一种安全有效方式实现,CAS发挥的巨大优势是:CAS不会招致内核级别的任何开销,编译器发出CPU指令,如lock cmpxchg, lock xadd, lock addq,这可以像你从JVM中调用指令一样快,CAS提供了比锁更好的一种替代。

但是使用在某些场合CAS会导致开销增大,可以见Dave Dice等人的研究成果,Java程序员应该好好读一下这个报告,避免了很多关于CAS的误解。

下面是一个实现back-off竞争管理的代码,非常简单,替代了之前失败的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);
    }
 
}
<p>

测试结果如下,测试条件是: 64-bit Linux 3.5.0 (x86_64) with Intel(R) Core(TM) i7-3632QM CPU @ 2.20GHz (8 logical cores) using 64-bit Hotspot Java 1.7.0_25-b15.

在多个读,一个写的场景下,back-off和CAS没有什么区别,但是在一个读多个写以及多个读多个写的情况却不同:

[该贴被banq于2014-01-15 09:31修改过]

[该贴被banq于2014-01-16 08:25修改过]



              

5
wilsonp
2014-03-16 21:08

2014-01-15 09:29 "@banq"的内容
back-off竞争管理 ...

不是很清楚“back-off竞争管理”这个是什么竞争管理方式,在google上也找不到相应的介绍,请banq老师科普一下吧?