2 ms·
Aren’t the same data races possible in async without threads? As soon as you suspend one task and start another, you have the problem that the currently running
by fiddlerwoaroof 3y ago
Aren’t the same data races possible in async without threads? As soon as you suspend one task and start another, you have the problem that the currently running task can break the invariants of the suspended one, regardless of whether you’re doing a single-threaded event loop or threads running in parallel.
- eximius 3y agoI think you'd need to be violating some other rule of rust to do that. e.g., single mutable access.
- fnordpiglet 3y agoRust isn’t functional, so if you have state that’s shared in some way you can’t expect it to be immutable unless you manage it immutably. However you are assured that you won’t need to worry about thread safety and reentrant code in rust because you are guaranteed the same memory won’t be modified or modified/read at the same time by two threads. Obviously in single threaded asynchronous code this doesn’t happen anyways. That said, if you don’t use shared state that allows multiple borrows, you won’t see state changing between futures even in the single threaded cases due to the ownership model of rust.
- fiddlerwoaroof 3y agoYeah, this was more or less my impression.
- skybrian 3y agoIn a single-threaded system, you only need to worry about concurrency when there’s an await keyword. Everywhere else, it’s as if you have an exclusive lock. Any functions that aren’t async can be treated as atomic. This makes it much easier to reason about concurrency. With a multithreaded system, async or not, you have to worry about the concurrency issues that come up when sharing data between multiple threads, because that’s what you’re doing. It’s odd how Rust ended up with the worst of both worlds by default. I think people got overconfident because Rust otherwise handles multithreading so well.
- fiddlerwoaroof 3y ago> In a single-threaded system, you only need to worry about concurrency when there’s an await keyword. Everywhere else, it’s as if you have an exclusive lock Except that async code written this way in JavaScript/Typescript often ends up being subtly broken by evolution in where the awaits occur as the software is maintained. IMO, it’s generally better to design async code with a shared-nothing mentality anyways.
- skybrian 3y agoIn my experience a missing await is the most common bug. Inadvertently run something in the background for an instant race condition, and hard to find. I think there should be no default for how to call an async function from another async function. Both waiting for a response and not waiting (starting a "background task") should be acknowledged in the code. Perhaps not allowing a promise return value to be silently dropped would be enough. Sync functions are easy in comparison. Edit: I guess there is a lint rule: https://typescript-eslint.io/rules/require-await/ https://typescript-eslint.io/rules/require-await/