我出来了这个惊人的结果,我完全不知道原因: 我有两种缩写为:
的方法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不是同步,因此更多的线程可以同时处理代码。
任何原因??
答案 0 :(得分:4)
在我假设没有500个内核的机器上使用500个线程的开销,使用大约100-1000x的任务,只要在Map上执行查找以执行JVM可以检测到的代码就不会执行任何事情都可能产生随机结果。 ;)
您可能遇到的另一个问题是,使用synchronized执行更快的测试可以从使用synchronized获益,因为它会偏向对一个线程的访问。也就是说,它将你的多线程测试变回一个首先最快的单线程测试。
你应该将你得到的时间与进行循环的单个线程进行比较。如果这更快(我认为它会更快),那么它不是一个有用的多线程测试。
我的猜测是你在非同步代码之后运行同步代码。即JVM已经预热了一点。交换执行这些测试的顺序并多次运行它们会得到不同的结果。
答案 1 :(得分:0)
在非同步场景中: 1)等待获取地图段上的锁定,锁定,对地图执行操作,解锁,等待获取其他地图的一段锁定,锁定,在其他地图上执行操作,解锁。 段级锁定仅在并发写入段的情况下执行,在您的示例中看起来不是这种情况。
在同步方案中: 1)等待锁定,执行两个操作,解锁。
上下文切换所需的时间会产生影响吗?运行测试的机器有多少个核心? 地图是如何构建的,同样的密钥?