【问题标题】:GetAndDecrement Much Slower than GetAndIncrement.GetAndDecrement 比 GetAndIncrement 慢得多。
【发布时间】:2014-04-17 00:00:09
【问题描述】:

我发现在 Java 中使用 AtomicIntegersGetAndDecrementGetAndIncrement 慢得多。为什么会这样?

【问题讨论】:

  • 这个问题真的很模糊。你能用证据证明这一点吗?
  • 等等……这实际上正在发生……
  • 你能发布一些统计数据吗?我发现确实发生了这种情况,您能否对其进行测试并提供更直接的证据?

标签: java atomic atomicinteger


【解决方案1】:

第二个更快。

AtomicInteger a = new AtomicInteger(1);

long start1 = System.nanoTime();
a.decrementAndGet(); 
System.out.println("Time: " + (System.nanoTime()-start1));

AtomicInteger b = new AtomicInteger(1);

long start2 = System.nanoTime();
a.incrementAndGet();
System.out.println("Time: " + (System.nanoTime()-start2));

在我的机器上,打印出来的是:

时间:49264

时间:4105

但是,如果我们交换两个操作的顺序:

AtomicInteger a = new AtomicInteger(1);

long start1 = System.nanoTime();
a.incrementAndGet();
System.out.println("Time: " + (System.nanoTime()-start1));

AtomicInteger b = new AtomicInteger(1);

long start2 = System.nanoTime();
a.decrementAndGet();
System.out.println("Time: " + (System.nanoTime()-start2));

然后我们得到:

时间:43106

时间:7697

大概是 JVM 或处理器之类的东西在做一些运行时优化。

【讨论】:

    【解决方案2】:

    它们在我看来几乎一样 --

    public final int getAndIncrement() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return current;
        }
    }
    
    public final int getAndDecrement() {
        for (;;) {
            int current = get();
            int next = current - 1;
            if (compareAndSet(current, next))
                return current;
        }
    }
    

    【讨论】:

    • 运行它。当我运行它时,getAndDecrement() 方法花费了 5 倍的时间。运行并计时,不要发布假设。
    • 这只是源代码(诚然有点老了)。本来应该是一条评论,但那样的话就无法辨认了。
    • (可能是较新的实现将更流行的增量转移到本机方法,或类似的方法。)
    • 这与最新的实现相同。
    • 仍有可能增量被本机实现覆盖。另一种可能更可能的可能性是 JITC 优化了增量而不是减量,这可能是因为存在执行前者的本机指令。
    猜你喜欢
    • 2011-10-27
    • 1970-01-01
    • 2013-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-12
    • 1970-01-01
    相关资源
    最近更新 更多