2

在经历了以下问题之后, 同步块可以比 Atomics 更快吗?
我写了一个简单的程序来比较AtomicInteger和同步块的性能差异(在里面递增int)。每次我运行这个程序时,它给我的比率 > 100。我的笔记本电脑有 Intel Corei3,下面的行打印 4。

    System.out.println(Runtime.getRuntime().availableProcessors())

当我使用

    THREAD_COUNT = 1;

这个比率是最低的。它在 100 左右变化。对于

    THREAD_COUNT = 10;  

比例在800左右。

问题1:你能告诉我这是测试AtomicInteger VS同步增量()方法性能差异的正确方法吗?

问题2:如果我增加THREAD_COUNT,比率增加,为什么?我认为这是因为更多的线程在同步语句中被阻塞并且需要更多的 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);
        }
    }
}
4

1 回答 1

0

问题1:你能告诉我这是测试AtomicInteger VS同步增量()方法性能差异的正确方法吗?

您的测试代码存在一些微妙的问题:

  • 如果你正在同步,LOCK那么counter不应该是volatile. 否则,代码将synchronized支付锁volatile.
  • 如果counter不是volatile,那么您将需要在LOCK读取 的值时进行同步counter
  • 你不应该在你的主线程中旋转。这将极大地影响您的性能测试。至少Thread.sleep(100);在你的循环中放一个。while
  • 事实证明,这Thread.currentThread().isInterrupted()在我的 Mac 上相当昂贵。不知道为什么。将其切换为 awhile(true)更改了数字。

有了这个,你就可以更好地测试这两者了,尽管这种孤立的测试除了你正在测试的东西之外并没有真正告诉我们任何东西。连续执行一百万个中断与将 20 个中断混合到实际代码中是非常不同的。

问题 2:如果我增加 THREAD_COUNT,比率会增加,为什么?我认为这是因为更多的线程在同步语句中被阻塞并且需要更多的 CPU 任务。请评论。

工作通过AtomicInteger.incrementAndGet()旋转直到测试和设置成功。这与进行锁的获取、增量和释放非常不同。如果不知道精确的操作系统线程处理细节,很难解释这里发生了什么,我不确定这在所有情况下都是正确的。

在我的测试中,随着线程数量越来越多于我的处理器数量,该比率往往会出现相当大的波动。随着更多线程的添加,synchronize处理显然受到并发性增加的影响,尽管我不确定我还能从中得到什么。

于 2016-05-24T20:45:23.090 回答