为什么访问volatile变量比成员慢约100?

时间:2012-06-21 05:35:44

标签: java performance volatile

这里我写了一个关于本地,成员,易变成员的访问速度的测试:

public class VolatileTest {

public int member = -100;

public volatile int volatileMember = -100;

public static void main(String[] args) {
    int testloop = 10;
    for (int i = 1; i <= testloop; i++) {
        System.out.println("Round:" + i);
        VolatileTest vt = new VolatileTest();
        vt.runTest();
        System.out.println();
    }
}

public void runTest() {
    int local = -100;

    int loop = 1;
    int loop2 = Integer.MAX_VALUE;
    long startTime;

    startTime = System.currentTimeMillis();
    for (int i = 0; i < loop; i++) {
        for (int j = 0; j < loop2; j++) {
        }
        for (int j = 0; j < loop2; j++) {
        }
    }
    System.out.println("Empty:" + (System.currentTimeMillis() - startTime));

    startTime = System.currentTimeMillis();
    for (int i = 0; i < loop; i++) {
        for (int j = 0; j < loop2; j++) {
            local++;
        }
        for (int j = 0; j < loop2; j++) {
            local--;
        }
    }
    System.out.println("Local:" + (System.currentTimeMillis() - startTime));

    startTime = System.currentTimeMillis();
    for (int i = 0; i < loop; i++) {
        for (int j = 0; j < loop2; j++) {
            member++;
        }
        for (int j = 0; j < loop2; j++) {
            member--;
        }
    }
    System.out.println("Member:" + (System.currentTimeMillis() - startTime));

    startTime = System.currentTimeMillis();
    for (int i = 0; i < loop; i++) {
        for (int j = 0; j < loop2; j++) {
            volatileMember++;
        }
        for (int j = 0; j < loop2; j++) {
            volatileMember--;
        }
    }
    System.out.println("VMember:" + (System.currentTimeMillis() - startTime));

}
}

这是我的X220(I5 CPU)的结果:

回合:1 空:5 本地:10 会员价:312 VMember:33378

回合:2 空:31 本地:0 会员价:294 VMember:33180

回合:3 空:0 本地:0 会员价:306 VMember:33085

回合:4 空:0 本地:0 会员价:300 VMember:33066

回合:5 空:0 本地:0 会员价:303 VMember:33078

回合:6 空:0 本地:0 会员价:299 VMember:33398

回合:7 空:0 本地:0 会员价:305 VMember:33139

回合:8 空:0 本地:0 会员价:307 VMember:33490

回合:9 空:0 本地:0 会员价:350 VMember:35291

轮:10 空:0 本地:0 会员价:332 VMember:33838

让我感到惊讶的是,对volatile组件的访问速度比普通成员慢100倍。我知道有一些关于volatile成员的突出特性,比如对它的修改将立即对所有线程可见,对volatile变量的访问点起到“内存屏障”的作用。但所有这些副作用能否成为100倍慢的主要原因?

PS:我还在Core II CPU机器上进行了测试。大概是9:50,大约慢5倍。看起来这也与CPU拱形有关。 5次仍然很大,对吗?

4 个答案:

答案 0 :(得分:7)

不会缓存volatile成员,因此可以直接从主内存中读取它们。

答案 1 :(得分:3)

访问volatile变量可防止CPU在访问之前和之后重新排序指令,这通常会降低执行速度。

答案 2 :(得分:3)

访问volatile会阻止一些JIT优化。如果你有一个没有真正做任何事情的循环,尤其重要,因为JIT可以优化这些循环(除非你有一个volatile字段)如果你运行循环“long”,那么descrepancy应该增加更多。

在更实际的测试中,您可能希望volatile对于cirtical代码要慢30%到10倍。在大多数真正的程序中,它几乎没有什么区别,因为CPU足够聪明,可以“实现”只有一个核心使用volatile字段并缓存它而不是使用主存储器。

答案 3 :(得分:0)

使用volatile将直接从内存中读取数据,以便cpu的每个内核都将在下一次从变量获取更改时,不使用cpu缓存,该缓存将不使用寄存器,L1〜L3缓存技术来读取

  1. 注册1个时钟周期
  2. L1缓存4个时钟周期
  3. 二级缓存11个时钟周期
  4. L3缓存30〜40个时钟周期
  5. 内存100个以上时钟周期

这就是为什么使用volatile时结果要慢100倍的原因。

相关问题