Vì AtomicInteger có thể có ít nhất một trình tự cường độ chậm hơn một int được bảo vệ bởi đồng bộ hóa, tại sao tôi lại muốn sử dụng AtomicInteger?
AtomicInteger nhanh hơn nhiều.
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);
}
in
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
Thêm một số tranh chấp như @assylias gợi ý. Nó cho thấy rằng khi bạn chỉ thực sự sử dụng một luồng, CPU có thể tối ưu hóa truy cập.
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<Future<Void>> futures = new ArrayList<>();
for(int t=0;t<8;t++) {
futures.add(es.submit(new Callable<Void>() {
public Void call() throws Exception {
for (int i = 0; i < runs; i += 2) {
synchronized (LOCK1) {
i1++;
}
synchronized (LOCK2) {
i2++;
}
}
return null;
}
}));
}
for (Future<Void> 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<Future<Void>> futures = new ArrayList<>();
for(int t=0;t<8;t++) {
futures.add(es.submit(new Callable<Void>() {
public Void call() throws Exception {
for (int i = 0; i < runs; i += 2) {
ai1.incrementAndGet();
ai2.incrementAndGet();
}
return null;
}
}));
}
for (Future<Void> 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);
}
in
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
Nguồn
2012-07-26 13:46:32
Tôi hiện đang thực sự bối rối. Đó không phải là những gì tôi hiểu được từ câu trả lời của @ Gray ở đây: http://stackoverflow.com/a/11125474/722603 Tôi đang thiếu gì? – ef2011
Tôi nghĩ anh ta có nghĩa là 'AtomicInteger' chậm hơn * không đồng bộ * 'int'; anh ấy đang nói về lý do tại sao bạn không nên thay thế tất cả các thành viên 'int' bằng' AtomicInteger' mà không cần biện minh. Nhưng nó không phải là một đơn đặt hàng của cường độ chậm hơn, bất kỳ nhiều hơn nó là một thứ tự của cường độ nhanh hơn. Đối với hầu hết các phần này là tất cả những khác biệt nhỏ mà chúng ta đang nói đến. –
Tôi nhớ đọc ở đâu đó rằng cơ chế khóa cũng khác nhau đối với nội dung nguyên tử, nhưng không thể lấy tham chiếu đó ngay bây giờ. Tôi cũng có thể sai. – kosa