AtomicLong的incrementAndGet方法如何在内部工作?

时间:2013-04-13 20:46:55

标签: java atomicity compare-and-swap atomic-long

我在多线程代码中使用incrementAndGet AtomicLong方法来衡量一些客户端代码的性能。

@Override
public void run() {


   long start = System.nanoTime();

   attributes = client.getAttributes(columnsList);

   long end = System.nanoTime() - start;

   final AtomicLong before = select.putIfAbsent(end / 1000000L, new AtomicLong(1L));
        if (before != null) {
            before.incrementAndGet();
        }
}

在上面的代码中,我试图测量多长时间 -

client.getAttributes(columnsList);

正在接受。

据我所知incrementAndGet方法将以原子方式将当前值增加1。 这意味着每个线程可能会等待其他线程增加值。我是对的吗?意味着它会被阻止?

这是否会影响我测量任何方法性能的方式?这意味着它会为该测量添加一些额外的时间吗?

为什么我要问这是因为我试图对大部分客户端代码和服务器端代码进行基准测试,如果我需要测量每个方法花费多少时间,那么我就是这么做 - < / p>

无论我想测量什么代码,我通常将下面的行放在该方法的上方

long start = System.nanoTime();

这两行采用相同的方法但具有不同的ConcurrentHashMap

long end = System.nanoTime() - start;

final AtomicLong before = select.putIfAbsent(end / 1000000L, new AtomicLong(1L));
    if (before != null) {
        before.incrementAndGet();
    }

因此,如果我使用incrementAndGet方法并且如果它为我的性能测量增加了额外的时间,那么我可能无法获得准确的结果?

更新: -

这是以下方法,我在F3的{​​{1}}上incrementAndGet时得到了。

所以这里有一个同步块。这意味着每个线程都会在这里等待其他线程。这是一个阻止电话。

eclipse

啊哈。我刚检查了我的JVM,与/** * Atomically increments by one the current value. * * @return the updated value */ public final synchronized long incrementAndGet() { //IBM-perf_AtomicLong ++value; //IBM-perf_AtomicLong return value; //IBM-perf_AtomicLong } 相比,我正在运行IBM JVM。因为我在一家公司工作,我无法改变这一点。

那么有没有办法避免这种基于锁的解决方案来衡量任何方法的性能/基准?请记住我正在运行IBM JVM。

感谢您的帮助。

1 个答案:

答案 0 :(得分:7)

请不要担心。除非您正在编写类似外汇平台的东西,否则这个微小的,微小的延迟并不重要。为了给你一个想法,我们将以纳秒级的顺序进行讨论,而在应用程序代码中,我们通常以毫秒为单位进行通话。此外,JVM的锁定已显着改善。如果您的争用率较低(这是常态),基于锁定的解决方案和非阻塞解决方案之间的性能差异将很小。

令人惊讶的是,IBM JVM使用AtomicLong的锁。我认为所有主要实现都使用非阻塞CAS。以下是使用CAS的常见实现:

/**
 * Atomically increments by one the current value.
 *
 * @return the updated value
 */
public final long incrementAndGet() {
    for (;;) {
        long current = get();
        long next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
}

对后续评论的回复:
根据经验,一个很粗略的规则,如果你目前的终端到终端的响应时间(或响应时间要求)为30ms以上,我真的不担心这是什么花的时间增加了长会在纳秒的境界。我几乎可以肯定你会发现其他优化的地方会给你更多的改进(例如毫秒)。

但是,您可以复制AtomicLong的Sun JVM实现以使用非阻塞实现来代替,因为IBM VM也应该具有CAS操作。如果您期望中等到高的争用(大量线程),这只会导致显着的改进。如果你不这样做,我认为锁定解决方案可以与当前的改进锁实现几乎相同(如果我记得的话,可以从JDK6获得)。

实际上,如果您的争用非常频繁,那么锁定可以比非阻塞解决方案执行得更好。所以你理想情况下必须使用两个实现并比较结果...这就是为什么我认为你不应该打扰,因为在那个时候,你可以在其他地方做了一些性能改进,给你的文学不止1通过这里解决你可以获得的改善。