当 AtomicInteger 比 synchronized 快时
When AtomicInteger is faster than synchronized
我已经阅读了大量文章,其中提到 AtomicInteger class 比同步构造更快。我对 AtomicInteger 和“同步”做了一些测试,在我的测试中,同步比 AtomicInteger 快得多。我想了解出了什么问题:我的测试 class 不正确或 AtomicInteger 在其他情况下工作得更快?
这是我的测试class:
public class Main {
public static void main(String[] args) throws InterruptedException
{
// creating tester "synchronized" class
TesterSynchronized testSyn = new TesterSynchronized();
// Creating 3 threads
Thread thread1 = new Thread(testSyn);
Thread thread2 = new Thread(testSyn);
Thread thread3 = new Thread(testSyn);
// start time
long beforeSyn = System.currentTimeMillis();
// start
thread1.start();
thread2.start();
thread3.start();
thread1.join();
thread2.join();
thread3.join();
long afterSyn = System.currentTimeMillis();
long delta = afterSyn - beforeSyn;
System.out.println("Test synchronized: " + delta + " ms");
// _______________________________________________________
// creating tester "atomicInteger" class
TesterAtomicInteger testAtomic = new TesterAtomicInteger();
thread1 = new Thread(testAtomic);
thread2 = new Thread(testAtomic);
thread3 = new Thread(testAtomic);
// start time
long beforeAtomic = System.currentTimeMillis();
// start
thread1.start();
thread2.start();
thread3.start();
thread1.join();
thread2.join();
thread3.join();
long afterAtomic = System.currentTimeMillis();
long deltaAtomic = afterAtomic - beforeAtomic;
System.out.println("Test atomic integer: " + deltaAtomic + " ms");
}
}
// Synchronized tester
class TesterSynchronized implements Runnable {
public int integerValue = 0;
public synchronized void run() {
for (int i = 0; i < 1_000_000; i++)
integerValue++;
}
}
// AtomicInteger class tester
class TesterAtomicInteger implements Runnable {
AtomicInteger atomicInteger = new AtomicInteger(0);
public void run() {
for (int i = 0; i < 1_000_000; i++)
atomicInteger.incrementAndGet();
}
}
测试参数:3个线程和1_000_000增量;
结果:
Test synchronized: 7 ms. Test atomic integer: 51 ms
我很乐意理解为什么会这样。
UPD
如果将 synchronized 方法 更改为 synchronized 块.
,测试将是正确的
// Synchronized tester
class TesterSynchronized implements Runnable {
public int integerValue = 0;
public void run() {
for (int i = 0; i < 1_000_000; i++) {
synchronized (this) {
integerValue++;
}
}
}
}
代码中的明显区别是 AtomicIntger
版本允许线程交错访问,而 synchronized
版本依次执行每个线程的整个循环。
可能还有其他问题。例如,JVM 可能会合并对 synchronized
块的多次调用。根据平台的不同,incrementAndGet
可能不是一个原子操作,而是作为一个 CAS 循环实现的——如果争用很高,那可能是个问题(我对此并不完全确定)。
不管怎样安排,如果你有多个线程同时修改同一个内存位置,它不会很快。
我已经阅读了大量文章,其中提到 AtomicInteger class 比同步构造更快。我对 AtomicInteger 和“同步”做了一些测试,在我的测试中,同步比 AtomicInteger 快得多。我想了解出了什么问题:我的测试 class 不正确或 AtomicInteger 在其他情况下工作得更快?
这是我的测试class:
public class Main {
public static void main(String[] args) throws InterruptedException
{
// creating tester "synchronized" class
TesterSynchronized testSyn = new TesterSynchronized();
// Creating 3 threads
Thread thread1 = new Thread(testSyn);
Thread thread2 = new Thread(testSyn);
Thread thread3 = new Thread(testSyn);
// start time
long beforeSyn = System.currentTimeMillis();
// start
thread1.start();
thread2.start();
thread3.start();
thread1.join();
thread2.join();
thread3.join();
long afterSyn = System.currentTimeMillis();
long delta = afterSyn - beforeSyn;
System.out.println("Test synchronized: " + delta + " ms");
// _______________________________________________________
// creating tester "atomicInteger" class
TesterAtomicInteger testAtomic = new TesterAtomicInteger();
thread1 = new Thread(testAtomic);
thread2 = new Thread(testAtomic);
thread3 = new Thread(testAtomic);
// start time
long beforeAtomic = System.currentTimeMillis();
// start
thread1.start();
thread2.start();
thread3.start();
thread1.join();
thread2.join();
thread3.join();
long afterAtomic = System.currentTimeMillis();
long deltaAtomic = afterAtomic - beforeAtomic;
System.out.println("Test atomic integer: " + deltaAtomic + " ms");
}
}
// Synchronized tester
class TesterSynchronized implements Runnable {
public int integerValue = 0;
public synchronized void run() {
for (int i = 0; i < 1_000_000; i++)
integerValue++;
}
}
// AtomicInteger class tester
class TesterAtomicInteger implements Runnable {
AtomicInteger atomicInteger = new AtomicInteger(0);
public void run() {
for (int i = 0; i < 1_000_000; i++)
atomicInteger.incrementAndGet();
}
}
测试参数:3个线程和1_000_000增量; 结果:
Test synchronized: 7 ms. Test atomic integer: 51 ms
我很乐意理解为什么会这样。
UPD 如果将 synchronized 方法 更改为 synchronized 块.
,测试将是正确的// Synchronized tester
class TesterSynchronized implements Runnable {
public int integerValue = 0;
public void run() {
for (int i = 0; i < 1_000_000; i++) {
synchronized (this) {
integerValue++;
}
}
}
}
代码中的明显区别是 AtomicIntger
版本允许线程交错访问,而 synchronized
版本依次执行每个线程的整个循环。
可能还有其他问题。例如,JVM 可能会合并对 synchronized
块的多次调用。根据平台的不同,incrementAndGet
可能不是一个原子操作,而是作为一个 CAS 循环实现的——如果争用很高,那可能是个问题(我对此并不完全确定)。
不管怎样安排,如果你有多个线程同时修改同一个内存位置,它不会很快。