All the pitfalls of concurrency are there - in particular when executing non-idempotent functions multiple times before previous executions finish, then you need mutexes!
All the pitfalls of concurrency are there - in particular when executing non-idempotent functions multiple times before previous executions finish, then you need mutexes!
This is one of those "in practice, theory and practice are different" situations.
There is nothing in the async world that looks like a parallel race condition. Code runs to completion until it deterministically yields, 100% of the time, even if the location of those yields may be difficult to puzzle out.
And so anyone who's ever had to debug and reason about a parallel race condition is basically laughing at that statement. It's just not the same.
No, because async can be (quote often is) used to perform I/O, whose time to completion does not need to be deterministic or predictable. Selecting on multiple tasks and proceeding with the one that completes first is an entirely ordinary feature of async programming. And even if you don't need to suffer the additional nondeterminism of your OS's thread scheduler, there's nothing about async that says you can't use threads as part of its implementation.
Yes yes, in theory they're the same. That's the joke.
If you need to synchronize stuff in the program you can use normal plain variables, since it's guaranteed that your task will be never interrupted till you give control back to the scheduler by performing an await operation.
In a way, async code can be used to implement mutex (or something similar) themself: it's a technique that I use often in JavaScript, to implement stuff that works like a mutex or a semaphores with just promises to syncronize stuff (e.g. you want to be sure that a function that itself does async operations inside is not interrupted, it's possible to do so with promises and normal JS variables).
await foo()
await bar()
and execute them in two threads transparently for you. It just happens, like the Python GIL, that it doesn't. Your JS implementation actually already has mutexes because web workers with shared memory bring true parallelization along with the challenges that come with.Please don't implement this yourself
This isn't even remotely true; plenty of languages have both async and concurrency, probably more than ones that don't. C# was the language that originated async/await, not JavaScript, and it certainly has concurrency, as do Swift, Python. Rust, and many more. You're conflating two independent proprieties of JavaScript as language and incorrectly inferring a link between them that doesn't actually exist.
In particular promise.all([f,f,f]) where I want to ensure that I only Run the body of f a single time.