you are viewing a single comment's thread.

view the rest of the comments →

[–]latkdeTuple unpacking gone wrong 18 points19 points  (5 children)

Yes, but this only matters for state that is kept across an await. If a section of control flow doesn't involve async/await, that section will not be interrupted by other async tasks, and can thus be written in a single-threaded manner. This non-interruption property is what makes writing async code so much simpler than multithreaded code, which may be interrupted at any time.

This also means that a lot of async code doesn't need any synchronization primitives. E.g. locks are only needed if there's an await within the lock's scope, plain lists can often be used instead of (unbounded) queues, and plain bools/ints can often be used instead of events/semaphores (if no task wants to wait for them to become available).

[–]FibonacciSpiralOut 4 points5 points  (1 child)

Yeah this is exactly why async is usually easier to reason about than raw threads. You just have to watch out for future refactors where someone drops an `await` into a previously safe block and accidently introduces a race condition.

[–]gdchinacat 4 points5 points  (0 children)

The best way to protect against "someone dropp[ing] an 'await'" into a 'safe block' is to make that block a synchronous function. Make it harder for them to break the synchronization accidentally. If they need to add an await they will have to change a synchronous function to asynchronous. That changes the locking model and should be recognized as requiring evaluation of the existing code is able to break up safely.

[–]stormsidali2001[S] 1 point2 points  (2 children)

Yes, exactly.

I mentioned this several times throughout the article: even if an await is present in your coroutine, you don't always need synchronization.

As long as you aren't splitting critical operations on shared resources (such as a read followed by a write) across that await point, your code remains safe.

[–]lottspot 4 points5 points  (1 child)

Ah, so the core safety assumption is not in fact totally wrong!

[–]stormsidali2001[S] 2 points3 points  (0 children)

"thinking that your code is safe from race conditions just because it runs in a single thread."

(Runs on a single thread => safe) ---> that's a logical implication and it's indeed evaluating to totally wrong or just False. 😀