多线程减慢程序的速度

问题描述:

根据我的理解,越来越多的threads或进入并行会减少时间,但在这里,我看到一个缓慢的Object.hashCode,它占用了两倍的时间来计算默认的哈希码对同一数量的对象运行4个线程vs 1个线程。多线程减慢程序的速度

我认为这需要花费相当的时间或更少的时间来并行执行此操作。

但是当我们运行下面的代码。我们可以看到,每个线程都有相同的工作量,因此您希望运行4个线程可能需要大约与运行单个线程相同的时间。

我看到~4秒为2.3秒,而1秒为0.9秒。

public class Test { 

    private static final int THREAD_COUNT = 1; 
    private static final int ITERATIONS = 20000000; 

    public static void main(final String[] args) throws Exception { 
     long start = System.currentTimeMillis(); 
     new Test().run(); 
     System.err.println(System.currentTimeMillis() - start); 
    } 

    private final ExecutorService service = Executors.newFixedThreadPool(THREAD_COUNT, new ThreadFactory() { 
     private final ThreadFactory factory = Executors.defaultThreadFactory(); 

     @Override 
     public Thread newThread(final Runnable r) { 
      Thread thread = factory.newThread(r); 
      thread.setDaemon(true); 
      return thread; 
     } 
    }); 

    private void run() throws Exception { 
     Callable<Void> work = new java.util.concurrent.Callable<Void>() { 
      @Override 
      public Void call() throws Exception { 
       for (int i = 0; i < ITERATIONS; i++) { 
        Object object = new Object(); 
        object.hashCode(); 
       } 
       return null; 
      } 
     }; 
     @SuppressWarnings("unchecked") 
     Callable<Void>[] allWork = new Callable[THREAD_COUNT]; 
     Arrays.fill(allWork, work); 
     List<Future<Void>> futures = service.invokeAll(Arrays.asList(allWork)); 
     for (Future<Void> future : futures) { 
      future.get(); 
     } 
    } 

} 

注:我看到这篇文章C# Multithreading但因为它是C#所以我能够掌握它,有人能帮助我理解从JVM的角度

+0

线程并没有真正做任何工作,因为它只是放弃了'hashCode()'的结果。所以JIT编译器可能会跳过'call()'内的整个循环,除非我错了。 'call()'方法目前看起来很没用,因为它总是返回'null'。 –

+0

为了记录:您已阅读此:http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – GhostCat

+0

在查看代码后,它应该要注意的是,如果1个线程执行W个工作量(操作),则N个线程执行N * W个操作。因此,并行减少执行时间并非如此。这个代码根本不需要多线程。 – Eugene

相同的,如果我走"new Object()"在循环之外,我看到相对多线程性能的显着提高。

似乎"new Object()"将消除GC干扰。

在这种情况下,默认的hashCode涉及:

  1. 计算一个hashcode
  2. 经由原子compare-and-swap操作

在紧张的使用原子CAS的安装此进object头循环有效地串行化功能代码的核心部分,导致连续执行相当大比例的"work loop"

+0

感谢刚刚在谷歌上搜索答案时发现... :) –

+0

@ GhostCat-不,我现在得到了我的答案,明白每一件事情 –