Search code examples
algorithmconcurrencysynchronizationvotinglinden-scripting-language

Simplest possible voting/synchronization algorithm


What would be a simplest algorithm one or more people could use to decide who of them should perform some task? There is one task, which needs to be done only once, and one or more people. People can speak, that is, send messages one to another. Communication must be minimal, and all people use the exact same algorithm.

One person saying "I'm doing it" is not good enough since two persons may say it at a same time.

Simplest that comes to my mind is that each person says a number and waits a bit. If somebody responds in that time, the person with lower number "wins" and does the task. If nobody responds, person says that she's doing it and does it. When she says that she does it, everybody else backs off. This should be enough to avoid two persons doing the task in the same time (since there is wait/handhake period), but might need a "second round" if both persons say the same number.

Is there something simpler?

For those curious, I'm trying to synchronize several copies of SecondLife LSL script to do something only once.


Solution

  • In the end, I came up with a solution that works pretty well. I started thinking - why not try to minimize collisions (that is, try to have only one volunteer) instead of negotiating who does the task?

    The key principles are:

    • if the volunteer is the only volunteer, he's the one who does it
    • if two (or more) people want to do the task at the same time, make both wait for a random period to minimize collisions

    The algorithm is:

    1. if you hear "Finished!" at any time, even while waiting, restart
    2. wait for random amount of time (between 30m and 1h 30m)
    3. wait for constant predefined amount of time (one cycle, 24h)
    4. if there's a task to be done
      1. say "I'm alive!"
      2. wait 5 seconds (assuming that task is always done in less than 5 seconds!)
      3. if you hear "I'm alive!" during that time
        1. repeat "I'm alive!"
        2. goto 2
      4. else (if you don't hear anything)
        1. do the task
        2. say "Finished!"
    5. restart

    That basically means that there is a grammar of two possible signals/messages ("I'm alive!" and "Finished!").

    Say n is number of clients/people. In ideal conditions, that also means 2 messages per cycle when no collisions for any n. When there are collisions, this means +2 messages per cycle per collision. There are low chances for it, but in the worst case scenario there are n messages plus the task doesn't get done in this cycle. In the worst case scenario where task does get done, there are n+1 messages.

    Possible simplifications

    Since I can afford to skip a cycle (task doesn't get done in this cycle), but I can't afford to have another task done before next cycle, I make everyone wait for one cycle in beginning. If you don't have "one task per cycle" requirement, you can skip step 3. There is still no guarantee that the task will be done in one cycle, but with large values in step 2, small values in step 4.2, and small number of clients/people we'd have pretty good chances.

    Algorithm could work even with only one signal/message. We could skip step 1 and say "I'm alive!" in 4.4.2 as well, but only if 4.4.1 would make check in step 4 fail immediately.