# Synchronizing 2 loops in multi-threading

**URL:** <https://discourse.julialang.org/t/synchronizing-2-loops-in-multi-threading/52015>\
**Category:** Performance\
**Tags:** parallel, multithreading\
**Created:** [December 17, 2020, 11:03pm UTC](https://discourse.julialang.org/t/synchronizing-2-loops-in-multi-threading/52015 "2020-12-17T23:03:03Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![dopamine](https://avatars.discourse-cdn.com/v4/letter/d/e9a140/32.png) [@dopamine](https://discourse.julialang.org/u/dopamine)\
**Post date:** [December 17, 2020, 11:03pm UTC](https://discourse.julialang.org/t/synchronizing-2-loops-in-multi-threading/52015/1 "2020-12-17T23:03:03Z")

</div>

What’s the best way to synchronize 2 while loops, each running on its own thread?

In the example below, `loop1` runs 80 times per second while `loop2` (blocking/IO) runs 20 times per second. Currently, without any locks/synchronizations, the timing of the loops diverges away as time passes.

```julia
timer1 = Timer(0, interval=1/80)
timer2 = Timer(0, interval=1/20)

q_loop = Threads.Atomic{Bool}(true)

function loop1()
    wait(timer1)
    while q_loop.value
        # do task...
        wait(timer1)
    end
end

function loop2()
    wait(timer2)
    while q_loop.value
        # do a different task involving IO (blocking)
        wait(timer2)
    end
end

function loop()
    @sync begin
        Threads.@spawn loop1()
        Threads.@spawn loop2()
    end
end

# start and run the loops until the user requests to stop
q_loop.value = true
@async loop()

# stop the loops
q_loop.value = false

```

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [December 17, 2020, 11:45pm UTC](https://discourse.julialang.org/t/synchronizing-2-loops-in-multi-threading/52015/2 "2020-12-17T23:45:40Z")

</div>

If the loops perform independent operations, then why do they need to be synchronized? If the are interdependent, synchonize by communicating (via a Channel).

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [December 18, 2020, 1:40pm UTC](https://discourse.julialang.org/t/synchronizing-2-loops-in-multi-threading/52015/3 "2020-12-18T13:40:13Z")

</div>

I’m not sure what all your constraints are but I feel like the easiest way to keep the two functions in lock step are to run them off of one timer like:

```julia
q_loop = Threads.Atomic{Bool}(true)

function loop1(ch1)
    for _ in ch1
        println("Quick")
    end
end

function loop2(ch2)
    for _ in ch2
        println("Slow")
    end
end

function loop()
    ch1 = Channel{Bool}(16)
    ch2 = Channel{Bool}(16)
    q_loop[] = true

    @async begin
        sleep(2)
        q_loop[] = false
    end

    @sync begin
        @Threads.spawn loop1(ch1)
        @Threads.spawn loop2(ch2)

        local c = 1
        Timer(0, interval=1/80) do t
            if q_loop[] == false
                close(ch1)
                close(ch2)
                close(t)
            elseif c == 4
                put!(ch1, true)
                put!(ch2, true)
                c = 1
            else
                put!(ch1, true)
                c += 1
            end
        end
    end

end

```

Here you have 1 timer that runs at 1/80 which wakes up `loop1()` every tick and `loop2()` every 4th tick. The channels of size 16 give you a little bit of slop if `loop1()` takes over 1/80 a second to perform it’s operation or `loop2()` takes over 1/20 to do it’s thing. However if either loops takes longer consistently you are going to have a general slow down.

You could resolve this by checking the channels before putting `true` into them, if they are full generate some sort of alert. You could also replace the `Channel`s with `Event`s in which case if either loop takes to long it will just “miss” the next tick.
