java - 使用预定义 key 锁定的竞争条件解决方案

标签 java multithreading asynchronous concurrency race-condition

我有一个与子任务对象具有一对多关系的任务对象。两个对象都有状态字段。任务对象中子任务的状态可以在并发线程中同时更新。当一个子任务更新结束时,会检查同一任务对象下的另一个子任务的状态。如果全部完成,任务的状态将标记为已完成。数据库的更新发生在退出子任务更新方法之后。

public void updateSubTask(SubTask subTask, Status status) {
    subTask.setStatus(status);
    //check all subtask status
    if (Status.Completed.equals(status) {
        boolean allCompleted = true;
        for(SubTask otherTask : subTask.getParentTask().getSubTasks()){
           if (!otherTask.equals(subTask) && !Status.Completed.equals(otherTask.getStatus)) {
               allCompleted = false;
               break;
           }
        }
        if (allCompleted) {
            updateParentTask(subTask.getParentTask(), Status.Completed);
        }
    }
}

假设任务 A 下有两个子任务,分别称为子任务 1 和子任务 2。
1. 子任务1的update方法被线程A调用。
2. update方法被子任务2的线程B调用。
3. 线程 A 将子任务 1 更新为“已完成”,并检查子任务 2 的状态
4. 线程 B 将子任务 2 更新为“已完成”,并检查子任务 1 的状态
5. 线程 A 和 B 都将子任务 2 和 1 分别视为“未完成”,因此它们退出该方法,而不将任务 A 更新为“已完成”

我现在的任务 A 尚未完成,但所有子任务均已完成。

作为临时解决方案,我使用包含 HashMap 的单例对象。每次线程开始处理子任务时,都会首先检查 hashmap 是否包含子任务的主任务的任务 ID。如果是。我让该线程 hibernate 几秒钟,然后再次尝试检查。如果它不在 HashMap 中,则将该 ID 放入 HashMap 中并继续处理。处理后,该 ID 将从 hashmap 中删除。

目前这工作正常,但使用 Thread.sleep 方法似乎不是挂起线程的优雅方法。同步块(synchronized block)在这里不是一个选项,因为我仍然应该允许其他线程更新其他子任务,因为这些子任务位于不同的主任务下。

我可以在 java.concurrent 库(或任何其他库)中使用具有类似于我所描述的“锁和 key ”机制的东西吗?

最佳答案

简单答案:observer pattern ;可能基于你们好老PropertyChangeListener .

“子任务”既不应该担心其“父”任务的状态,也不应该担心其他“子任务”的状态。

对此问题的规范答案是“父”任务需要“倾听”其子任务内部正在发生的事情。

关于java - 使用预定义 key 锁定的竞争条件解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41629181/

相关文章:

java - 如何检测Unix终端字符编码?

java - 如何将 0 到无穷大的值限制为 0 到 1 的值?

java - 如何检测 Swing 线程策略违规

java - ActiveMQ 主题上的并行消息消费

java - Java 程序的优雅终止和终止信号的记录

javascript - 在 AngularJS 中异步调用 hprose.httpclient

javascript - 如何从异步调用返回响应?

java - apache PropertiesConfiguration 无法解析占位符

java - 需要后续帮助/建议 ---Java BankAccount 应用程序 - 在通过 switch 语句的情况下重用变量

javascript - 在嵌套循环中从 $.get() 返回数组