同步代码比非同步代码执行得更快

时间:2011-09-10 10:27:53

标签: java multithreading synchronization

我出来了这个惊人的结果,我完全不知道原因: 我有两种缩写为:

的方法
private static final ConcurrentHashMap<Double,Boolean> mapBoolean = 
        new ConcurrentHashMap<Double, Boolean>();
private static final ConcurrentHashMap<Double,LinkedBlockingQueue<Runnable>> map
        = new ConcurrentHashMap<Double, LinkedBlockingQueue<Runnable>>();


protected static <T> Future<T> execute(final Double id, Callable<T> call){
// where id is the ID number of each thread
synchronized(id)
{
   mapBoolean.get();// then do something with the result
   map.get();//the do somethign with the result
}
}

protected static <T> Future<T> executeLoosely(final Double id, Callable<T> call){

 mapBoolean.get();// then do something with the result
 map.get();//the do somethign with the result

 }

}

在使用超过500个线程进行性能分析,并且每个线程分别调用上述每个方法400次时,我发现execute(..)执行至少比executeLoosely(..)好500倍,这很奇怪,因为executeLoosely不是同步,因此更多的线程可以同时处理代码。

任何原因??

2 个答案:

答案 0 :(得分:4)

在我假设没有500个内核的机器上使用500个线程的开销,使用大约100-1000x的任务,只要在Map上执行查找以执行JVM可以检测到的代码就不会执行任何事情都可能产生随机结果。 ;)

您可能遇到的另一个问题是,使用synchronized执行更快的测试可以从使用synchronized获益,因为它会偏向对一个线程的访问。也就是说,它将你的多线程测试变回一个首先最快的单线程测试。

你应该将你得到的时间与进行循环的单个线程进行比较。如果这更快(我认为它会更快),那么它不是一个有用的多线程测试。

我的猜测是你在非同步代码之后运行同步代码。即JVM已经预热了一点。交换执行这些测试的顺序并多次运行它们会得到不同的结果。

答案 1 :(得分:0)

在非同步场景中: 1)等待获取地图段上的锁定,锁定,对地图执行操作,解锁,等待获取其他地图的一段锁定,锁定,在其他地图上执行操作,解锁。 段级锁定仅在并发写入段的情况下执行,在您的示例中看起来不是这种情况。

在同步方案中: 1)等待锁定,执行两个操作,解锁。

上下文切换所需的时间会产生影响吗?运行测试的机器有多少个核心? 地图是如何构建的,同样的密钥?