AtomicInteger何时优先于同步?

由于AtomicInteger至少比synchronized保护的int慢一个数量级,为什么我要使用AtomicInteger?

例如,如果我想要的是以线程安全的方式增加int值,为什么不总是使用:

 synchronized(threadsafeint) { threadsafeint++; } 

而不是使用慢得多的AtomicInteger.incrementAndGet() ?

由于AtomicInteger至少比同步保护的int慢一个数量级,为什么我要使用AtomicInteger?

AtomicInteger要快得多。

 static final Object LOCK1 = new Object(); static final Object LOCK2 = new Object(); static int i1 = 0; static int i2 = 0; static final AtomicInteger ai1 = new AtomicInteger(); static final AtomicInteger ai2 = new AtomicInteger(); public static void main(String... args) throws IOException { for(int i=0;i<5;i++) { testSyncInt(); testAtomicInt(); } } private static void testSyncInt() { long start = System.nanoTime(); int runs = 10000000; for(int i=0;i< runs;i+=2) { synchronized (LOCK1) { i1++; } synchronized (LOCK2) { i2++; } } long time = System.nanoTime() - start; System.out.printf("sync + incr: Each increment took an average of %.1f ns%n", (double) time/runs); } private static void testAtomicInt() { long start = System.nanoTime(); int runs = 10000000; for(int i=0;i< runs;i+=2) { ai1.incrementAndGet(); ai2.incrementAndGet(); } long time = System.nanoTime() - start; System.out.printf("incrementAndGet: Each increment took an average of %.1f ns%n", (double) time/runs); } 

版画

 sync + incr: Each increment took an average of 32.4 ns incrementAndGet: Each increment took an average of 20.6 ns sync + incr: Each increment took an average of 31.4 ns incrementAndGet: Each increment took an average of 12.9 ns sync + incr: Each increment took an average of 29.6 ns incrementAndGet: Each increment took an average of 12.9 ns sync + incr: Each increment took an average of 35.1 ns incrementAndGet: Each increment took an average of 16.6 ns sync + incr: Each increment took an average of 29.9 ns incrementAndGet: Each increment took an average of 13.0 ns 

添加一些争用为@assylias建议。 它表明,当您只使用一个线程时,CPU可以优化访问。

 static final Object LOCK1 = new Object(); static final Object LOCK2 = new Object(); static int i1 = 0; static int i2 = 0; static final AtomicInteger ai1 = new AtomicInteger(); static final AtomicInteger ai2 = new AtomicInteger(); public static void main(String... args) throws ExecutionException, InterruptedException { for(int i=0;i<5;i++) { testSyncInt(); testAtomicInt(); } } private static void testSyncInt() throws ExecutionException, InterruptedException { long start = System.nanoTime(); final int runs = 1000000; ExecutorService es = Executors.newFixedThreadPool(2); List> futures = new ArrayList<>(); for(int t=0;t<8;t++) { futures.add(es.submit(new Callable() { public Void call() throws Exception { for (int i = 0; i < runs; i += 2) { synchronized (LOCK1) { i1++; } synchronized (LOCK2) { i2++; } } return null; } })); } for (Future future : futures) { future.get(); } es.shutdown(); long time = System.nanoTime() - start; System.out.printf("sync + incr: Each increment took an average of %.1f ns%n", (double) time/runs/2); } private static void testAtomicInt() throws ExecutionException, InterruptedException { long start = System.nanoTime(); final int runs = 1000000; ExecutorService es = Executors.newFixedThreadPool(2); List> futures = new ArrayList<>(); for(int t=0;t<8;t++) { futures.add(es.submit(new Callable() { public Void call() throws Exception { for (int i = 0; i < runs; i += 2) { ai1.incrementAndGet(); ai2.incrementAndGet(); } return null; } })); } for (Future future : futures) { future.get(); } es.shutdown(); long time = System.nanoTime() - start; System.out.printf("incrementAndGet: Each increment took an average of %.1f ns%n", (double) time/runs/2); } 

版画

 sync + incr: Each increment took an average of 478.6 ns incrementAndGet: Each increment took an average of 191.5 ns sync + incr: Each increment took an average of 437.5 ns incrementAndGet: Each increment took an average of 169.8 ns sync + incr: Each increment took an average of 408.1 ns incrementAndGet: Each increment took an average of 180.8 ns sync + incr: Each increment took an average of 511.5 ns incrementAndGet: Each increment took an average of 313.4 ns sync + incr: Each increment took an average of 441.6 ns incrementAndGet: Each increment took an average of 219.7 ns 

如果你真的想获得更多关于为什么java.util.concurrent东西更好以及与经典同步方法相比有什么不同的细节,请阅读此链接 (以及整个博客)