首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何实现LongAccumulator,使其更有效率?

如何实现LongAccumulator,使其更有效率?
EN

Stack Overflow用户
提问于 2014-04-10 06:49:10
回答 2查看 2.9K关注 0票数 12

据我所知,新的Java (8)引入了新的同步化工具,如LongAccumulator (在原子包下)。

在文档中,它指出当来自多个线程的变量更新频繁时,LongAccumulator会更高效。

我想知道如何实施才能提高效率?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-10 17:57:54

这是一个非常好的问题,因为它显示了共享内存并发编程的一个非常重要的特性。在详细讨论之前,我得退一步。看一看下面的课:

代码语言:javascript
复制
class Accumulator {
    private final AtomicLong value = new AtomicLong(0);
    public void accumulate(long value) {
        this.value.addAndGet(value);
    }
    public long get() {
        return this.value.get();
    }
}

如果您创建这个类的一个实例,并从循环中的accumulate(1)单线程调用方法,那么执行将非常快。但是,如果从(两个线程)调用同一个实例上的方法,则执行速度将慢两个数量级。

您必须看看内存体系结构,才能了解发生了什么。现在大多数系统都有一个非均匀存储器存取。特别是,每个核心都有自己的L1缓存,通常被构造成64位字节的高速缓存行。如果一个核心在一个内存位置上执行原子增量操作,它首先必须获得对相应的缓存行的独占访问。这是昂贵的,如果它还没有独占访问,因为需要与所有其他核心协调。

要解决这个问题,有一个简单而违反直觉的技巧。看一看下面的课:

代码语言:javascript
复制
class Accumulator {
    private final AtomicLong[] values = {
        new AtomicLong(0),
        new AtomicLong(0),
        new AtomicLong(0),
        new AtomicLong(0),
    };
    public void accumulate(long value) {
        int index = getMagicValue();
        this.values[index % values.length].addAndGet(value);
    }
    public long get() {
        long result = 0;
        for (AtomicLong value : values) {
            result += value.get();
        }
        return result;
    }
}

乍一看,由于额外的操作,这个类似乎更昂贵。但是,它可能比第一个类快几倍,因为它具有更高的概率,即执行核心已经具有对所需缓存行的独占访问权。

要做到这一点,你必须考虑更多的事情:

  • 不同的原子计数器应该位于不同的缓存线上。否则,您将一个问题替换为另一个问题,即虚假共享。在Java中,您可以为此使用long[8 * 4],并且只使用索引081624
  • 柜台的数目必须明智地选择。如果不同的计数器太少,那么缓存开关仍然太多。如果计数器太多,则在L1缓存中浪费空间。
  • 方法getMagicValue应该返回一个与核心id有关联的值。

总之,对于某些用例,LongAccumulator更有效,因为它使用冗余内存进行频繁使用的写操作,为了减少次数,缓存行必须在内核之间进行交换。另一方面,读取操作稍微昂贵一些,因为它们必须创建一致的结果。

票数 24
EN

Stack Overflow用户

发布于 2014-04-10 14:24:38

通过这个

http://codenav.org/code.html?project=/jdk/1.8.0-ea&path=/Source%20Packages/java.util.concurrent.atomic/LongAccumulator.java

看上去像个旋转锁。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22980568

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档