Understanding Distributed Programming in Julia

According to the documentation, fetch() will - Wait for a [`Task’] (Tasks · The Julia Language) to finish, then return its result value.

For the code and its output given below, I have the following questions -

  1. How does isready(task1) , written immediately below spawning of task1, not return false? Instead it waits for task1 to finish and then prints True. Why is that? How can I achieve the functionality to test at a point whether a spawned function is currently over or not without forcing it to get over at that point?
  2. Can I be sure that any line written below fetch(task1) will not be executed before task1 is complete?
using TickTock
using Distributed
# julia -p auto includes Distributed and 
# adds number of workers = julia -p `nproc` on Linux
# julia -p %NUMBER_OF_PROCESSORS% on Windows

@everywhere function f1(x)
    for i in 1:10000000000
        x = 2*x + 1 - x
        # if(i%1000000000 == 0)
        #     println(x)
        # end
    end
    println(x)
end

tick()
task1 = @spawn  f1(101.12)
println(isready(task1))
task2 = @spawn  f1(102.12)
task3 = @spawn f1(103.12)
fetch(task1)
print("task1 fetched. Now fetching task2 and task3, akin to wait(task1)")
fetch(task2)
fetch(task3)
tock()

The output received is given below

[ Info:  started timer at: 2024-04-11T01:32:04.573
From worker 2:    1.0000000101119999e10
true #Output for is task ready
task1 fetched. Now fetching task2 and task3, akin to wait(task1)      
From worker 4:    1.0000000103119999e10
From worker 3:    1.0000000102119999e10
[ Info:         95.472729208s: 1 minute, 35 seconds, 472 milliseconds ```

Please see the documentation for isready(::Distributed.Future).

https://docs.julialang.org/en/v1/stdlib/Distributed/#Base.isready-Tuple{Distributed.Future}

 isready(rr::Future)

  Determine whether a Future has a value stored to it.

  If the argument Future is owned by a different node, this call
  will block to wait for the answer. It is recommended to wait for
  rr in a separate task instead or to use a local Channel as a
  proxy:

  p = 1
  f = Future(p)
  errormonitor(@async put!(f, remotecall_fetch(long_computation, p)))
  isready(f)  # will not block

The documentation mentions the usage for objects of type Future. Could you tell me how to check if the spawned task object type can be checked to see if it has been completed without having to block or wait for it.
Or should I be converting my task into a Future object type?

To be clear, what you think are “tasks” here are actually Futures.

julia> using Distributed

julia> f = @spawn 1
Future(2, 1, 6, ReentrantLock(nothing, 0x00000000, 0x00, Base.GenericCondition{Base.Threads.SpinLock}(Base.IntrusiveLinkedList{Task}(nothing, nothing), Base.Threads.SpinLock(0)), (8, 481371906128, 481374757240)), nothing)