For coroutines, why ‘debug app’ gives different re...
# coroutines
h
For coroutines, why ‘debug app’ gives different result than ‘run app’ in logcat? The result also depends on the no. of breakpoints used and where these breakpoints are used in debug mode? Why so?
b
Concurrent code is nondeterministic so you may get different results even in the same mode running it multiple times Anyway, to get a better answer you have to provide a piece of code with more details
h
this is the code and these are results in run and debug mode respectively
Screenshot 2024-02-06 at 1.27.52 PM.png,Screenshot 2024-02-06 at 1.28.07 PM.png
b
ChildJob's body is posted to main thread and execution proceed to
delay(3000)
immediately (e.g. so if you put
Log.d(TAG, "before delay(3000)")
before
delay(3000)
you will see that log is always there before
Child Started
) . As I said concurrent code is non-deterministic (unpredictable) in general. In your piece of code if main thread hangs for 2s+ after the
delay(3000)
call you will see the logs from the second screenshots. So here is a potential timeline of what is happening in your case 1.
Parent Started
log is printed 2. Child job is posted to main thread (its execution hasn't started!
Child Started
isn't printed) 3. delay(3000) is executed, effectively posting
Parent Ended
Log with 3000ms delay. 4. Main thread somehow hangs for 2100ms (e.g. there was some heavy runnable in the main thread) 5. Child job is executing,
Child Started
printed.
Child Ended
posted with 1000ms delay 6. delay(3000) from step 3 completes,
Parent Ended
printed 7. delay(1000) from step 5 completes,
Child Ended
printed. One potential way to make this particular example predictable is to add start parameter to child's launch
Copy code
val childJob = launch(start = CoroutineStart.UNDISPATCHED) {
in this case you will ensure
delay(1000)
is scheduled strictly before
delay(3000)
. Overall don't try to make a concurrent code predictable/pseudo-serial by using just delays - it will never work properly in 100% of real scenarios
c
Shouldn't
delay
be always equivalent to a
yield
? I don't understand how it would take 3s for the other coroutine to be scheduled.
b
there are a bunch of other pieces that use Main dispatcher. Any heavy blocking work may make your coroutine not scheduled in 3s+
https://pl.kotl.in/JIVMuB84X Just an example that reproduces this behavior
c
I see, that makes sense, thanks.
h
Thanks a lot🙌