Ste*_*hen 5 java concurrency hashmap
运行以下类时,ExecutionService通常会死锁.
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorTest {
public static void main(final String[] args) throws InterruptedException {
final ExecutorService executor = Executors.newFixedThreadPool(10);
final HashMap<Object, Object> map = new HashMap<Object, Object>();
final Collection<Callable<Object>> actions = new ArrayList<Callable<Object>>();
int i = 0;
while (i++ < 1000) {
final Object o = new Object();
actions.add(new Callable<Object>() {
public Object call() throws Exception {
map.put(o, o);
return null;
}
});
actions.add(new Callable<Object>() {
public Object call() throws Exception {
map.put(new Object(), o);
return null;
}
});
actions.add(new Callable<Object>() {
public Object call() throws Exception {
for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) {
iterator.next();
}
return null;
}
});
}
executor.invokeAll(actions);
System.exit(0);
}
}
Run Code Online (Sandbox Code Playgroud)
那么为什么会这样呢?或者更好 - 我如何编写测试以确保自定义抽象映射的实现是线程安全的?(某些实现具有多个映射,另一个实现具有缓存实现等)
一些背景:这发生在Windows上的Java 1.6.0_04和1.6.0_07下.我知道问题来自sun.misc.Unsafe.park():
下面的大多数答案都是关于HashMap的非线程安全性,但我在HashMap中找不到锁定的线程 - 它全部在ExecutionService代码中(和Unsafe.park()).我明天会仔细研究这些话题.
所有这一切都是因为自定义抽象Map实现不是线程安全的,所以我开始确保所有实现都是线程安全的.本质上,我想确保我对ConcurrentHashMap等的理解正是我所期望的,但却发现ExecutionService奇怪地缺乏......
Rob*_*anu 16
您正在使用一个众所周知的非线程安全类并抱怨死锁.我没有看到这里的问题.
另外,怎么样? ExecutionService
strangely lacking
Run Code Online (Sandbox Code Playgroud)
?
这是一个常见的误解,通过使用例如一个HashMap,你会在最得到一些陈旧的数据.见一个漂亮的竞争条件你怎么能这样做只是炸毁你的JVM.
理解为什么会发生这种情况是一个非常棘手的过程,需要了解JVM和类库的内部结构.
至于ConcurrentHashMap,只需阅读javadoc - 它应该澄清你的问题.如果没有,请查看Java Concurrency in Practice.
更新:
我设法重现你的情况,但这并不是一个僵局.其中一个actions永远不会完成执行.堆栈跟踪是:
"pool-1-thread-3" prio=10 tid=0x08110000 nid=0x22f8 runnable [0x805b0000]
java.lang.Thread.State: RUNNABLE
at ExecutorTest$3.call(ExecutorTest.java:36)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Run Code Online (Sandbox Code Playgroud)
它看起来像我链接到的确切情况 - HashMap被调整大小,并且由于调整迭代器大小的内部机制被卡在无限循环中.
发生这种情况时,invokeAll永远不会返回并且程序挂起.但它既不是僵局,也不是活锁,而是竞争条件.
| 归档时间: |
|
| 查看次数: |
7568 次 |
| 最近记录: |