在完成以下问题后
Can synchronized blocks be faster than Atomics? ,
我编写了一个简单的程序来比较 AtomicInteger 和同步块(synchronized block)(在其中递增 int)的性能差异。每次我运行这个程序时,它都会给我 ratio > 100。
我的笔记本电脑有 Intel Corei3,下一行显示 4。
System.out.println(Runtime.getRuntime().availableProcessors())
当我使用
THREAD_COUNT = 1;
比率最小。它在 100 左右变化。对于
THREAD_COUNT = 10;
比率在800左右。
问题 1:请问这是测试 AtomicInteger VS synchronized increment() 方法性能差异的正确方法吗?
问题 2:如果我增加 THREAD_COUNT
,比率会增加,为什么?我认为这是因为更多的线程在 synchronized 语句中被阻塞并且需要更多的 CPU 任务。请评论。
package concurrent.atomic;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Performance {
private static final AtomicInteger atomicInt = new AtomicInteger(0);
private static volatile int counter = 0;
private static final Object LOCK = new Object();
private static final int THREAD_COUNT = 10;
public static void main(String[] args) {
System.out.println(Runtime.getRuntime().availableProcessors());
Runnable atomic = new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
int value = atomicInt.incrementAndGet();
//if (value % 1000 == 0)
//System.out.println("atomic value : "+value);
}
}
};
//System.out.println("1");
Runnable intCounter = new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
synchronized (LOCK) {
int value = ++counter;
//if (value % 1000 == 0)
//System.out.println("sync value "+value);
}
}
}
};
final ExecutorService atomicExecutor = Executors.newCachedThreadPool();
final ExecutorService primitiveExecutor = Executors.newCachedThreadPool();
for (int i = 0; i < THREAD_COUNT ; ++i) {
atomicExecutor.submit(atomic);
primitiveExecutor.submit(intCounter);
}
while (true) {
float ratio = (((float) (atomicInt.get() * 1.0) ) / counter) * 100;
System.out.println("ratio : " + ratio);
}
}
}
最佳答案
Question 1 : Can you please tell me is this the correct way to test the performance difference of AtomicInteger VS synchronized increment() method?
您的测试代码存在一些细微的问题:
- 如果您在
LOCK
上同步然后counter
不应该是volatile
.否则synchronized
代码正在为锁支付费用和volatile
. - 如果
counter
不是volatile
那么您将需要在LOCK
上同步当您读取counter
的值时. - 你不应该在你的主线程中旋转。这将极大地影响您的性能测试。放一个
Thread.sleep(100);
在你的while
至少循环。 - 结果是
Thread.currentThread().isInterrupted()
在我的 Mac 上相当昂贵。不知道为什么。将其切换为while(true)
改变了数字。
有了这个,您就可以更好地测试这两者,尽管这种孤立的测试除了您正在测试的内容外,并没有真正告诉我们任何其他信息。连续执行 100 万次中断与将 20 次中断混合到实际代码中是非常不同的。
Question 2 : If I increase THREAD_COUNT, ratio increases, why? I think it is because more threads get blocked at synchronized statement and requires more task for CPU. Please comment.
AtomicInteger.incrementAndGet()
通过旋转工作,直到测试和设置成功。这与进行锁获取、递增和释放非常不同。在不了解精确的操作系统线程处理细节的情况下,很难解释这里发生的事情,我不确定这在所有情况下都是正确的。
在我的测试中,随着线程数量越来越多于我的处理器数量,该比率往往会出现相当大的波动。随着更多线程的添加,synchronize
处理显然受到并发性增加的影响,尽管我不确定我还能从中得到什么。
关于java - AtomicInteger 与 Java 中的同步 int 变量 : performance difference,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15949192/