JuliaDatabases / LibPQ.jl

A Julia wrapper for libpq
MIT License
217 stars 51 forks source link

Multiple `async_execute`s may not always execute in sequence? #278

Open tanmaykm opened 1 year ago

tanmaykm commented 1 year ago

The docstring for async_execute mentions: https://github.com/iamed2/LibPQ.jl/blob/2c0547daef005e160aa60cb529d4969a670befbc/src/asyncresults.jl#L203-L204

The actual implementation does this for synchronization in the method: https://github.com/iamed2/LibPQ.jl/blob/2c0547daef005e160aa60cb529d4969a670befbc/src/asyncresults.jl#L270

But it is not clear if that's something that can guarantee the desired behavior. The doubt is based on these questions:

In this example below, that is what happens:

julia> using Base.Threads

julia> function test1()
           lck = Threads.Condition()
           val = 10
           @sync begin
               for idx in 1:50
                   @async begin
                       lock(lck) do
                           val = idx
                       end
                   end     
               end
           end
           println("val: $val")
       end
test1 (generic function with 1 method)

julia> test1()
val: 50

julia> test1()
val: 50

But making the task yield randomly makes the result different every time:

julia> function test2()
           lck = Threads.Condition()
           val = 10
           @sync begin
               for idx in 1:50
                   @async begin
                       sleep(rand())
                       lock(lck) do
                           val = idx
                       end
                   end     
               end
           end
           println("val: $val")
       end
test2 (generic function with 1 method)

julia> test2()
val: 45

julia> test2()
val: 8

The question is in absence of any random yield (as in test2), is the execution order (as in test1) something that is guaranteed in Julia?