当前位置: 首页 > 知识库问答 >
问题:

Java同步int变量:性能差异

酆奇文
2023-03-14

经过以下问题后,同步块能比原子更快吗<我编写了一个简单的程序来比较AtomicInteger和synchronized块(其中int递增)的性能差异。每次我运行这个程序,它都会给我一个比率

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

当我使用

    THREAD_COUNT = 1;

该比率最小。它在100左右变化

    THREAD_COUNT = 10;  

比率约为800。

问题1:你能告诉我这是测试AtomicInteger和synchronized increment()方法性能差异的正确方法吗?

问题2:如果我增加THREAD\u计数,比率会增加,为什么?我认为这是因为更多的线程在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);
        }
    }
}

共有1个答案

拓拔辰钊
2023-03-14

问题1:你能告诉我这是测试AtomicInteger和synchronized increment()方法性能差异的正确方法吗?

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

  • 如果在锁上同步,则计数器不应是易失的。否则,同步的代码将支付锁和易失性的费用

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

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

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

 类似资料:
  • 问题内容: 我只是意识到我需要在一个方面同步大量的数据收集代码,但是性能才是真正的问题。如果性能下降太多,我的工具将被丢弃。我将分别将int和long写入各种数组,ArrayList和Map。应用程序将有多个线程将进行功能调用,这将由我的方面进行介绍。我应该注意什么样的事情会对性能产生负面影响?哪种代码模式更有效? 特别是我有一种方法可以调用许多其他数据记录方法: 这些方法通常会添加纵横比字段的增

  • 问题内容: 我注意到的和方法中有一个奇怪的构造: 考虑到JIT最有可能将其视为无操作,因此在本地对象上进行同步有什么意义? 问题答案: 在代码获取对象的监视器之后,立即将对对象的引用存储到中,该对象是组成节点的全局可见节点数组,这些节点组成了以下内容: 此时,在同一线程上执行其他修改方法的其他线程在遍历全局数组时可能会遇到此不完整的节点,换句话说,引用已转义。 虽然在构造时就不可能对新创建的对象进

  • 问题内容: Java中的最终变量是什么?例如:如果我在函数中编写final关键字的含义是什么? 另外,什么时候我要使用最终变量(既作为类变量又作为函数变量)? 为什么必须将同步块中的变量声明为final? 问题答案: 基本上,这只是意味着您无法更改该值。对于实例变量,您必须在构造函数中(或使用变量初始值设定项)分配所有最终变量一次(并且仅分配一次)。同步是一个非常正交的概念。 将 局部 变量设为f

  • 问题内容: 同步和异步AJAX调用有什么区别?何时使用同步以及何时异步? 问题答案: 在最基本的级别上,当您希望调用在后台发生时,您可以使用异步模式,而当您希望代码等待直到调用完成时,则可以使用同步模式。 异步模式是AJAX调用的常用方法,因为通常在事件上附加一个回调函数,以便您可以在服务器端数据就绪时进行响应,而不必等待数据到达。

  • 问题内容: 从变量读取的速度比从常规字段读取的速度慢多少? 更具体地说,简单对象创建比访问变量快还是慢? 我认为它足够快,因此与每次创建实例相比,拥有实例要快得多。但这是否也适用于字节[10]或字节[1000]? 编辑:问题是调用get 时真正发生了什么?如果那只是一个领域,就像其他领域一样,那么答案将是“它总是最快的”,对吗? 问题答案: 运行未发布的基准测试,我的计算机上每次迭代大约需要35个

  • 问题内容: 编写之间是否存在性能差异(如果有) 与 另外,如果我们在参数签名中进行结构分解,会获得或失去任何性能?参见example3 我认为在这种情况下example3是编写函数的最佳方法? 功能性反应组件示例: 问题答案: 由于您的代码将被编译/缩小,因此不会有任何性能问题。 注意,使用React,您的代码将被转译,其作用与 在babel编译器在线测试仪上检查结果