volatile的int比AtomicInteger快

时间:2012-08-18 12:39:33

标签: java

我目前正在做一个示例练习,我发现一个奇怪的观察,如果我用挥发性程序替换AutomicInteger运行得更快。注意:我只做读操作。

代码:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class Main {

AtomicInteger integer  = new AtomicInteger(100000000);
// volatile int integer= 100000000;

public static void main(String[] args) {
// We will store the threads so that we can check if they are done
List<Thread> threads = new ArrayList<Thread>();
 long start = System.currentTimeMillis();
 Main main = new Main();
// We will create 500 threads

for (int i = 0; i < 500; i++) {
  Runnable task = new MyRunnable(main.integer);
  Thread worker = new Thread(task);
  // We can set the name of the thread
  worker.setName(String.valueOf(i));
  // Start the thread, never call method run() direct
  worker.start();
  // Remember the thread for later usage
  threads.add(worker);
}
int running = 0;
do {
  running = 0;
  for (Thread thread : threads) {
    if (thread.isAlive()) {
      running++;
    }
  }
  System.out.println("We have " + running + " running threads. ");
} while (running > 0);

System.out.println("Total Time Required :" +(System.currentTimeMillis()- start));
}
} 

MyRunnable类:

 import java.util.concurrent.atomic.AtomicInteger;

public class MyRunnable implements Runnable {
private final AtomicInteger countUntil;

MyRunnable(AtomicInteger countUntil) {
    this.countUntil = countUntil;
}

@Override
public void run() {
    long sum = 0;
    for (long i = 1; i < countUntil.intValue(); i++) {
        sum += i;
    }
    System.out.println(sum);
}
}

此程序在我的机器上使用AutomicInteger运行所需的时间。

  

所需总时间:102169

     

所需总时间:90375

此程序在我的机器上使用volatile运行所需的时间

  

所需总时间:66760

     

所需时间:71773

这是否意味着volatile也比AutomicInteger更快进行读取操作?

4 个答案:

答案 0 :(得分:6)

阅读上下文中的

AtomicInteger基本上是围绕volatile int的简化包装:

private volatile int value;

public final int get() {
    return value;
}

public int intValue() {
    return get();
}

不要指望包装器比单独包装的值更快。如果JVM采用内联,它只能 volatile int


提示:如果你“只进行阅读操作”,这将更快:

static final int integer= 100000000;

答案 1 :(得分:1)

这个问题取决于特定的JVM,硬件和操作系统,因此唯一可能的答案是“可能”。

答案 2 :(得分:1)

  

volatile int比AtomicInteger

更快

访问和更新原子的记忆效应通常遵循挥发性规则,如Java™语言规范的section 17.4中所述。以下是与原子类型相比的volatile int的回退。

  • get具有读取volatile变量的记忆效应。

  • set具有写入(赋值)volatile变量的记忆效应。

  • lazySet具有写入(分配)volatile变量的记忆效应,除了它允许使用后续(但不是先前的)内存操作进行重新排序,这些内存操作本身不会对普通的非易失性写入施加重新排序约束。在其他用法上下文中,为了垃圾回收,可以在忽略输出时应用lazySet,这是一个永远不会再次访问的引用。

  • weakCompareAndSet以原子方式读取并有条件地写入变量,但不会创建任何先前发生的排序,因此不提供与weakCompareAndSet目标之外的任何变量的先前或后续读取和写入的保证。

  • compareAndSet和所有其他读取和更新操作(如getAndIncrement)都具有读取和写入volatile变量的内存效果。

答案 3 :(得分:0)

挥发性int可能比AtomicInteger快,如果很少有应用程序可以注意到这一点。 AtomicInteger提供了更广泛的潜在用途。