# Communication between two threads in Julia without blocking

**URL:** https://discourse.julialang.org/t/communication-between-two-threads-in-julia-without-blocking/77637
**Category:** General Usage
**Tags:** question
**Created:** [March 9, 2022, 3:07pm UTC](https://discourse.julialang.org/t/communication-between-two-threads-in-julia-without-blocking/77637 "2022-03-09T15:07:32Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Tine](https://avatars.discourse-cdn.com/v4/letter/t/9de053/32.png) [@Tine](https://discourse.julialang.org/u/Tine)
#### Post date: [March 9, 2022, 3:07pm UTC](https://discourse.julialang.org/t/communication-between-two-threads-in-julia-without-blocking/77637/1 "2022-03-09T15:07:33Z")

</div>

Hi!  
I am building a system that consist of multiple threads doing different work. For the purpose of this post, I am simplifying the code.

My system:

```julia
using ThreadPools

function work()
    (timer) -> begin
        stop = isready(running) && fetch(running) isa Stop
        if stop
            close(timer)
        else
            println("Hello!")
            schedule()
        end
    end
end

function schedule()
    Timer(work(), 2)
end

function manager()
    # Schedule first work()
    schedule()

    # Run till a signal to stop is received
    stop = isready(running) && fetch(running) isa Stop
    while ! stop
        if isready(sig)
            take!(sig)
            println("Received signal!!!")
        end

        stop = isready(running) && fetch(running) isa Stop
    end
end

function send_signal()
    sleep(8)
    put!(sig, true)
end

struct Stop end
running = Channel{Stop}(1)

sig = Channel{Bool}(1)

w1 = @tspawnat 2 manager()
errormonitor(w1)

w2 = @tspawnat 3 send_signal()
errormonitor(w2)

sleep(20)
put!(running, Stop())

```

So we have one thread (`w2`) that only put an element in the Channel `sig` after 8 seconds. Then we have another thread: `w1`, which has two main jobs. First, it has to periodically call `work()`. In the example, this happen every other second. The other job it has to do is to check if a signal has come on the Channel `sig`.

The system is supposed to run as long as I want it do. In the example, it will run in 20s, before a Stop signal is sent which will stop `w1` and the timer.

The problem is that in `manager()` the process of waiting for a signal in `sig` is blocking the execution of `work()`. How can I run this simultaneously, without introducing another thread?

---

<div class="post-metadata">

### Author: ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)
#### Post date: [March 9, 2022, 6:32pm UTC](https://discourse.julialang.org/t/communication-between-two-threads-in-julia-without-blocking/77637/2 "2022-03-09T18:32:59Z")

</div>

I could imagine to solve this with a shared variable guarded by a `ReentrantLock` using `trylock`…  
Will try if necessary…

---

<div class="post-metadata">

### Author: ![Tine](https://avatars.discourse-cdn.com/v4/letter/t/9de053/32.png) [@Tine](https://discourse.julialang.org/u/Tine)
#### Post date: [March 10, 2022, 8:17am UTC](https://discourse.julialang.org/t/communication-between-two-threads-in-julia-without-blocking/77637/3 "2022-03-10T08:17:54Z")

</div>

Hmmm… I don’t understand how that will work…

---

<div class="post-metadata">

### Author: ![djholiver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djholiver/32/50470_2.png) [@djholiver](https://discourse.julialang.org/u/djholiver)
#### Post date: [March 10, 2022, 9:19am UTC](https://discourse.julialang.org/t/communication-between-two-threads-in-julia-without-blocking/77637/4 "2022-03-10T09:19:48Z")

</div>

Hi,

I’m using my phone so can’t play with the above code but what your describing is a pattern often applied in Actors and there happens to be a Julia [implementation](https://github.com/JuliaActors/Actors.jl) (that I’ve not used yet) that may prove useful

Regards,

---

<div class="post-metadata">

### Author: ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)
#### Post date: [March 10, 2022, 11:23am UTC](https://discourse.julialang.org/t/communication-between-two-threads-in-julia-without-blocking/77637/5 "2022-03-10T11:23:16Z")

</div>

I’m far from being an expert on this, but when a task has to wait for one of several conditions, I think it is easier to have only one `Channel` that stores all events, rather than having one `Channel` per event type.

This is a significant rewrite, only loosely based on your original example, but I believe it does what you want (for your MWE; perhaps not for your real application)

```julia
@enum Event WORK SIGNAL STOP
events = Channel{Event}(32)

timer = Timer(2, interval=2) do _
    put!(events, WORK)
end

w1 = Threads.@spawn begin
    sleep(8)
    put!(events, SIGNAL)
end

w2 = Threads.@spawn begin
    while true
        evt = take!(events)
        if evt == WORK
            println("Hello!")
        elseif evt == SIGNAL
            println("Received signal!")
        elseif evt == STOP
            println("Terminating")
            close(timer)
            return
        else
            println("Unknown event $evt")
        end
    end
end

sleep(20)
put!(events, STOP)

wait(w1)
wait(w2)

```
