【发布时间】:2015-12-02 01:14:17
【问题描述】:
我通过比较同步方法测试了多线程中的原子整数有多快,但我得到的结果是原子整数比同步方法慢。
我阅读了 Java API 参考,并且了解 Atomic Integer 比多线程中的同步更快。
所以我想知道为什么我用 Atomic Integer 得到了不好的结果。 我的测试代码错了?
这是我的代码
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicThreadTest {
// Number of thread to run
private static final int THREAD_NUM = 1000;
// Repetition number to count up
private static final int ROOP_NUM = 200000;
// Base counter class
private abstract class Counter implements Runnable {
@Override
public void run() {
for (int i = 0; i < ROOP_NUM; i++) {
increment();
}
}
// Increment method
public abstract void increment();
// Get result of calculation
public abstract int getResult();
// Get name of the class
@Override
public String toString() {
return getClass().getSimpleName();
}
}
// Use no thread safe
private static int count = 0;
private class NoThreadSafeCounter extends Counter {
@Override
public void increment() {
count++;
}
@Override
public int getResult() {
return count;
}
}
// Use volatile
private static volatile int volatileCount = 0;
private class VolatileCounter extends Counter {
@Override
public void increment() {
volatileCount++;
}
@Override
public int getResult() {
return volatileCount;
}
}
// Use synchronized
private static int synchronizedCount = 0;
private class SynchronizedCounter extends Counter {
@Override
public synchronized void increment() {
synchronizedCount++;
}
@Override
public int getResult() {
return synchronizedCount;
}
}
// Use AtomicInteger
private static AtomicInteger atomicCount = new AtomicInteger(0);
private class AtomicCounter extends Counter {
@Override
public void increment() {
atomicCount.incrementAndGet();
}
@Override
public int getResult() {
return atomicCount.get();
}
}
public static void main(String[] args) {
AtomicThreadTest testClass = new AtomicThreadTest();
Counter[] testCounter = {
testClass.new NoThreadSafeCounter(),
testClass.new VolatileCounter(),
testClass.new SynchronizedCounter(),
testClass.new AtomicCounter(),
};
for (Counter c : testCounter) {
System.out.println("-------------------------");
System.out.printf("Test for class : %s\n", c.toString());
try {
test(c);
} catch (InterruptedException e) {
System.out.println("Test halted");
} finally {
System.out.println("");
System.gc();
}
}
System.out.println("-------------------------");
}
public static void test(final Counter counter) throws InterruptedException {
System.out.printf("Start with threads : %d, roop : %d\n", THREAD_NUM, ROOP_NUM);
final long startTime = System.currentTimeMillis();
// Create THREAD_NUM threads and run them
Thread[] threads = new Thread[THREAD_NUM];
for (int i = 0; i < THREAD_NUM; i++) {
threads[i] = new Thread(counter);
threads[i].start();
}
// Wait for all threads other than this end
while (Thread.activeCount() > 1) {
Thread.sleep(10);
}
final long endTime = System.currentTimeMillis();
System.out.printf("Result %d, Expected %d\n", counter.getResult(), THREAD_NUM*ROOP_NUM);
System.out.printf("Time to calc : %d\n", endTime-startTime);
}
}
我得到了下面的结果。
-------------------------
Test for class : NoThreadSafeCounter
Start with threads : 1000, roop : 200000
Result 198785583, Expected 200000000
Time to calc : 127
-------------------------
Test for class : VolatileCounter
Start with threads : 1000, roop : 200000
Result 19162116, Expected 200000000
Time to calc : 4458
-------------------------
Test for class : SynchronizedCounter
Start with threads : 1000, roop : 200000
Result 200000000, Expected 200000000
Time to calc : 8426
-------------------------
Test for class : AtomicCounter
Start with threads : 1000, roop : 200000
Result 200000000, Expected 200000000
Time to calc : 15190
【问题讨论】:
-
你不应该调用
System.gc(),因为你不知道它什么时候会被执行。您没有使用大量内存,在执行期间您不太可能需要 GC -
顺便说一句,您的同步(最后的
while循环)很糟糕并且消耗了大量 CPU。你应该改用信号量之类的东西 -
我在 JMH 基准测试中得到的结果与您完全不同。在Github Gist 中查看。我的预期结果是 AtomicInteger 比同步更快。
-
-
在信号量的情况下,您的主线程将被阻塞,直到所有任务完成。当它被阻塞时,它不会消耗任何 CPU 时间,而您的循环正在主动等待,这意味着主线程以快速的频率主动唤醒、睡眠、唤醒、睡眠等。跨度>
标签: java synchronized atomicinteger