Nano Hash - криптовалюты, майнинг, программирование

Решение условия гонки с блокировкой с помощью предопределенного ключа

У меня есть объект Task с отношением «один ко многим» к объекту подзадачи. Оба объекта имеют поля состояния. Статус подзадачи в объекте задачи может обновляться одновременно в параллельных потоках. В конце обновления подзадачи проверяется состояние другой подзадачи в том же объекте задачи. Если все выполнено, статус задачи помечается как завершенный. Обновление базы данных происходит после выхода из метода обновления подзадачи.

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);
        }
    }
}

Предположим, что в задаче А есть две подзадачи, назовем их подзадачей 1 и подзадачей 2.
1. Метод обновления вызывается потоком А для подзадачи 1.
2. Метод обновления вызывается потоком Б для подзадачи 2.
3. Поток А обновляет подзадачу 1 до "завершена" и проверяет состояние подзадачи 2
4. Поток Б обновляет подзадачу 2 до "завершена" и проверяет статус подзадачи 1
5. Оба потока A и B считают подзадачи 2 и 1 соответственно "незавершенными", поэтому они выходят из метода, не обновляя задачу A до "завершенной"

Теперь у меня есть задача А, которая еще не завершена, но все подзадачи выполнены.

В качестве временного решения я использую одноэлементный объект, содержащий хэш-карту. Каждый раз, когда поток начинает обработку подзадачи, сначала проверяется хэш-карта, если она содержит идентификатор задачи основной задачи подзадачи. Если да. Я усыпляю этот поток на несколько секунд и пытаюсь проверить снова. Если его нет в хэш-карте, то этот идентификатор помещается в хэш-карту, и обработка продолжается. После обработки идентификатор удаляется из хэш-карты.

На данный момент это работает нормально, но использование метода Thread.sleep не кажется элегантным способом приостановить поток. Синхронизированные блоки здесь не подходят, потому что я должен разрешить другим потокам обновлять другие подзадачи, учитывая, что эти подзадачи находятся в другой основной задаче.

Есть ли что-то, что я мог бы использовать в библиотеке java.concurrent (или любой другой библиотеке в этом отношении), которая имеет механизм «замок и ключ», аналогичный тому, что я описал?


  • Могу ли я предложить описать ваш код, используя реальный код? Мне трудно следовать этому. 13.01.2017
  • что мне непонятно, так это то, почему подзадача должна проверять другие. Это как проверки NxN? 17.01.2017
  • @efekctive — когда подзадача завершена, другие подзадачи проверяются, чтобы увидеть, можно ли переместить родительскую задачу в статус завершенной. 17.01.2017
  • И это повторяется в каждой подзадаче. Это не имеет большого смысла 17.01.2017

Ответы:


1

Простой ответ: шаблон наблюдателя; возможно, на основе старого доброго PropertyChangeListener.

"Подзадача" не должна нести ответственности за статус своей "родительской" задачи или статус других "подзадач".

Канонический ответ на это состоит в том, что «родительская» задача должна «слушать», что происходит внутри ее дочерних элементов.

13.01.2017

2

На мой взгляд, ваша конструкция неоптимальна.

Что бы я сделал, так это заставить задачу отслеживать события в подзадачах (прослушивание завершения задачи).

Что вам нужно, так это синхронизировать две асинхронные подзадачи. Так что синхронизация должна происходить в Задаче. Вы можете использовать AtomicInteger (или даже логическое значение), чтобы узнать, когда вы закончите две подзадачи.

Итак, задача состоит в том, чтобы

  • прикрепить слушателя к подзадачам
  • начать выполнение подзадачи 1.
  • начать выполнение подзадачи 2.
  • Когда подзадача завершается, она уведомляет слушателя (задачу).
  • Задача получает уведомление и меняет свой статус на 1/2 выполненного.
  • Когда 2/2 будут завершены, запустите изменения БД или что-то еще, что вам нужно сделать.
13.01.2017
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..