这里我写了一个关于本地,成员,易变成员的访问速度的测试:
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次仍然很大,对吗?
答案 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缓存技术来读取>
这就是为什么使用volatile时结果要慢100倍的原因。