В конце концов, я нашел решение, которое работает довольно хорошо. Я начал думать - почему бы не попытаться свести к минимуму коллизии (то есть попытаться иметь только одного добровольца) вместо того, чтобы договариваться, кто выполняет задачу?
Ключевые принципы:
- если волонтер - единственный волонтер, он делает это
- если два (или более) человека хотят выполнить задачу одновременно, заставьте обоих ждать случайный период времени, чтобы минимизировать коллизии
Алгоритм:
- если вы слышите "Закончено!" в любое время, даже в ожидании, перезапустите
- ожидание случайного количества времени (от 30 до 1 ч 30 м)
- ожидание постоянного предварительно определенного количества времени (один цикл, 24 часа)
- если есть задача, которую нужно выполнить
- сказать "Я жив!"
- подождите 5 секунд (при условии, что задача всегда выполняется менее чем за 5 секунд!)
- если вы услышите "Я жив!" в течение этого времени
- повторить "Я жив!"
- Перейти к 2
- иначе (если вы ничего не слышите)
- выполнить задание
- сказать "Готово!"
- перезагрузка
Это в основном означает, что есть грамматика двух возможных сигналов / сообщений («Я жив!» И «Закончено!»).
Скажите, n число клиентов / человек. В идеальных условиях это также означает 2 сообщения за цикл, когда нет коллизий для любого n. При наличии коллизий это означает +2 сообщения за цикл за коллизию. Шансы на это малы, но в худшем случае есть n сообщений, плюс задача не выполняется в этом цикле. В худшем случае, когда задача выполнена, есть n + 1 сообщений.
Возможные упрощения
Поскольку я могу позволить себе пропустить цикл (задача не выполняется в этом цикле), но я не могу позволить себе выполнить другую задачу до следующего цикла, я заставляю всех ждать одного цикла в начале. Если у вас нет требования «одна задача на цикл», вы можете пропустить шаг 3. По-прежнему нет гарантии, что задача будет выполнена за один цикл, но с большими значениями на шаге 2, небольшими значениями на шаге 4.2 и небольшое количество клиентов / людей, у нас были бы довольно хорошие шансы.
Алгоритм может работать даже с одним сигналом / сообщением. Мы могли бы пропустить шаг 1 и сказать: «Я жив!» в 4.4.2, но только в том случае, если 4.4.1 немедленно провалит проверку на шаге 4.