【发布时间】:2021-03-18 06:11:46
【问题描述】:
我已经阅读了大量文章,其中说 AtomicInteger 类的工作速度比同步构造快。我对 AtomicInteger 和“同步”进行了一些测试,在我的测试中,同步比 AtomicInteger 快得多。我想了解发生了什么问题:我的测试类不正确或 AtomicInteger 在其他情况下工作得更快?
这是我的测试类:
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个增量; 结果:
测试同步:7 毫秒。测试原子整数:51 ms
我很高兴了解为什么会发生这种情况。
UPD 如果将同步方法更改为同步块,测试将是正确的。
// 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++;
}
}
}
}
【问题讨论】:
-
在您的同步测试器中,您正在获取一个锁,然后执行您的百万增量。在您的 AtomicInteger 示例中,您为每个增量获取和释放一个锁。
-
尝试将
synchronized包裹在integerValue++和AtomicInteger周围会更快。您无法比较这两种方法。 -
确实是个问题!改成同步块后测试结果为:Test synchronized: 244 ms Test atomic integer: 95 ms。
-
除了
synchronized的错误,你应该看看correct benchmarking in Java是怎么做的。在这个测试中,synchronized可能很慢,但在其他一些测试中,您希望避免影响结果的噪音。 -
原来的TesterSynchronized循环可以被编译器优化。执行那个循环是没有意义的。它可以立即将 1_000_000 分配给 integerValue 而不是进行 1M 增量。
标签: java concurrency synchronization volatile atomicinteger