gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:10:09 24 4
gpt4 key购买 nike

我在我的多线程代码中使用 AtomicLongincrementAndGet 方法来测量我们的一些客户端代码的性能。

@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 方法,如果它为我的性能测量增加了额外的时间,那么我可能无法获得准确的结果?

更新:-

这是下面的方法,我在 eclipseincrementAndGet 上执行 F3 时得到的。

所以这里有一个synchronized block 。这意味着每个线程都会在这里等待其他线程。这是一个阻塞调用。

/**
* 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,我正在运行 IBM JVMSUN JVM 进行比较。因为我在一家公司工作,所以我无法改变这件事。

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

感谢您的帮助。

最佳答案

别担心。除非您正在编写类似外汇平台之类的东西,否则这种微小的延迟无关紧要。为了给您一个想法,我们将以纳秒的数量级进行讨论,而在应用程序代码中我们通常以毫秒为单位进行讨论。此外,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;
}
}

对跟进评论的回应:
作为一个非常粗略的经验法则,如果您当前的端到端响应时间(或响应时间要求)超过 30 毫秒,我真的不会担心这一点,因为增加 long 所花费的时间都在纳秒范围内.我几乎可以肯定您会找到其他可以优化的地方,从而为您带来更多改进(例如毫秒)。

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

事实上,如果您有非常高的竞争,锁可以比非阻塞解决方案执行得更好。所以理想情况下你必须使用两个实现并比较结果......这就是为什么我认为你不应该打扰的原因,因为在那个时候,你可以在其他地方做出一些性能改进,让你在文学上获得超过 1通过解决这里问题可以获得的改进的百万倍。

关于java - AtomicLong 的 incrementAndGet 方法在内部如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15992745/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com