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

Java AtomicLong的incrementAndGet方法在内部是如何工作的?,java,atomicity,compare-and-swap,atomic-long,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 = sele

我在我的多线程代码中使用了
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这意味着每个线程可能会等待其他线程增加该值。我说得对吗?这意味着它将被阻止

这是否也会影响我衡量任何方法性能的方式?这意味着它也会给测量增加一些额外的时间

我之所以问这个问题,是因为我正在尝试对大多数客户端代码和服务器端代码进行基准测试,如果我需要测量每个方法所花费的时间,那么我就是这样做的-

无论我想度量什么代码,我通常都会在该方法的上方加上一行

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
方法,如果它给我的性能度量增加了额外的时间,那么我可能没有得到准确的结果

更新:-

这是下面的方法,我在
incrementAndGet中执行
eclipse中的
F3
时得到的

这里有一个同步块。这意味着每个线程将在这里等待其他线程。这是一个阻塞呼叫

/**
 * 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
}
啊。我刚刚检查了我的JVM,我运行的是
IBMJVM
,而不是
SUN JVM
。因为我在一家公司工作,在那里我无法改变这件事

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


谢谢你的帮助。

别担心。除非你写的是外汇平台之类的东西,否则这种微小的延迟就无关紧要了。让我们了解一下,我们是以纳秒为单位进行讨论的,而在应用程序代码中,我们通常以毫秒为单位进行讨论。此外,JVM的锁已显著改进。如果争用率较低(这是标准),那么基于锁的解决方案和非阻塞解决方案之间的性能差异将很小

令人惊讶的是,IBMJVM使用了原子长锁。我认为所有主要的实现都使用非阻塞CA。以下是使用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;
    }
}
对后续评论的回应:
作为一个非常粗略的经验法则,如果您当前的端到端响应时间(或响应时间要求)超过30毫秒,我真的不会担心这一点,因为无论花费多少时间来增加long,都会在纳秒范围内。我几乎可以肯定的是,您会找到其他地方进行优化,从而获得更大的改进(例如毫秒)

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


事实上,如果您有非常高的争用率,那么锁可以比非阻塞解决方案执行得更好。因此,理想情况下,您必须使用两个实现并比较结果。。。这就是为什么我认为你不应该费心的原因,因为在那段时间里,你可以在其他地方做一些性能改进,使你的文学水平比你在这里解决问题所能达到的提高100多万倍

我还对IBMJDK使用锁感到惊讶。我怀疑它实际上没有,并且@TechGeeky看到的代码不是实际执行的代码。它可能是库中的占位符代码,在运行时被一些特殊情况下的代码替换为。感谢Emno的建议。但在我的公司里,我正在做这个项目,哪怕是一毫秒也很重要。因为我们对客户端端到端的延迟要求非常严格。所以这就是我现在非常关心的原因。为什么?因为我正在对客户端和服务端代码进行负载和性能测试。因此,如果我的结果出错,那么这将影响最终结果。如果你能提供一些解决方案,那就太好了。@TechGeeky我曾在许多系统上工作过,这些系统的端到端延迟都在1毫秒以下。AtomicLong可能需要100纳秒的时间(当满足时),这并没有那么长,但最简单的解决方案是尽可能多地处理线程本地数据,而您一开始就没有这个问题。一种简单的方法可以测试某个内容是否是内在的(从JVM的代码中可以明显看出)就是将方法复制到另一个类中,并比较微基准测试。内在方法可以比另一个类中的相同代码快2-5倍。