【发布时间】:2016-01-16 10:08:56
【问题描述】:
鉴于 ConcurrentHashMap javadocs 状态:
"迭代器和枚举返回反映状态的元素 在迭代器创建时或之后的某个时间点的哈希表”
我想我可以保证在下面的示例中,一个或两个线程将调用 fireAllFinished()。有没有调用fireAllFinished()的情况?
ConcurrentHashMap<String, Boolean> taskToFinished = new ConcurrentHashMap();
taskToFinished.put("taskA", false);
taskToFinished.put("taskB", false);
public void checkForAllFinished() {
boolean allFinished = true;
for (Boolean taskFinished = tasksToFinished.values()) {
if (!taskFinished) {
allFinished = false;
break;
}
}
if (allFinished) {
fireAllFinished()
}
}
//Thread1
public void run() {
taskToFinished.put("taskA", true);
checkForAllFinished();
}
//Thread1
public void run() {
taskToFinished.put("taskB", true);
checkForAllFinished();
}
(我省略了一些线程创建代码。希望意图清楚)
更新:我已经看到了这个更笼统的问题:Is iterating ConcurrentHashMap values thread safe?,但想确认我的具体观点为
“在某个时候”
在处理乱序运行代码的多核机器时通常是一个不精确的概念,两个线程可能“同时”更新映射的不同段,并且设计上没有办法锁定整个 ConcurrentHashMap。
【问题讨论】:
-
此程序无法运行。方法
checkForAllFinished有一个局部变量allFinished,它是本地的。局部变量始终是线程安全的,因为它们位于堆栈上并且永远不会被其他线程看到。因此,您的checkForAllFinished方法将无法按预期工作。如果您将allFinished设为实例字段,则需要将其同步或设为volatile以防止数据过时。 -
@scottb 你说的没有错。
-
如果您正在等待完成一组任务,为什么不使用
Future? -
@Jason - 我创建了这个简化的示例来专注于一个特定的点。在实际系统中,每个任务都有一个状态工作流,其整体批处理状态源自任务,并且每个任务都可以重新运行。未来可能会有所帮助,但我仍然希望能回答最初的问题。
标签: java multithreading synchronization concurrenthashmap