Hacker News new | past | comments | ask | show | jobs | submit login

> Code written using threads is, at least to me, much more readable and easier to reason about.

It's “easier” because it lies to you and makes you assume that everything is sequential, but it's not, and sometime that “everything is sequential” abstraction is leaky, and you can't really see what's going on without diving to the bottom of every functions.

I've been accustomed so much to the transparency of async/await, that I now whish we had the same kind of thing for functions using blocking syscalls (for instance you could annotate the function with the `blocking` keyword and need to use `block` to call it) so you known you need to spawn a new thread if you don't want to wait until the completion of some I/O-bound function.




> “everything is sequential” abstraction is leaky,

Can you explain what details leak?

The sequential model was developed for programming because that's a natural way to reason about proccesses. `if then else`. `do this, then do that. The "async/await" designers seem to agree, as they attempt to tame async by emulating this behavior.

Note that to do anything other than sequential is extremely complicated to reason about, not because of computers, but because of logic/math. All sorts of concerns like: race conditions, synchronization, dead lock, etc are inherent.

Any approach that does not directly address these issues is the one that's creating a leaky abstraction.

> so you known you need to spawn a new thread if you don't want to wait until the completion.

All functions take "blocking time" to execute. It's a spectrum of how long you want to wait.


> Can you explain what details leak?

You answer half of it a few lines later:

> All sorts of concerns like: race conditions, synchronization, dead lock, etc are inherent. > Any approach that does not directly address these issues is the one that's creating a leaky abstraction.

By writing `await` you're telling your reviewers, coworkers and even your future self than your program stops executing sequentially at this step, and that other concurrent task can do things in the meantime. When using blocking code, the same thing can happen, but this is hidden from you.

But in my perspective as a back-end engineer, the biggest issue is related to latency: with annotations you know (and tell others: code is written once but read many time) what takes significant time, with threads and hidden yield point you don't. It looks sequential, but the latency is an observable behiavor that show it's not: the definition of a leaky abstraction.

> All functions take "blocking time" to execute. It's a spectrum of how long you want to wait

That's technically correct, but keep in mind that the magnitude difference between your typical REST API call and a CPU instruction is roughly the same as the difference between the size of a football field and the distance to the Sun…


> When using blocking code, the same thing can happen, but this is hidden from you.

I'm not convinced. I don't see how it is hidden from you. The blocking code works exactly as written. The mistaken assumption would be that your program will never be premempted or have to wait for resources.

> the magnitude difference

Rarely is a function call in C a single instruction. They are typically algorithms of non-constant complexity. So yes... but you're also picking the most extreme comparison. What about `fopen` vs `partial_sort`?


> It's “easier” because it lies to you

No, it really doesn't. If I make the wrong assumption that "everything is sequential", then it's not the paradigm lying to me.

Pretty much the first thing I learned about threads: I have to assume that my code can, and will, be interrupted at arbitrary points.

As long as I keep that in mind, there is very little that can surprise me. Because the other side of that coin reads: "Unless it branches into more threads of execution, each block itself will run sequentially, no matter what", which makes it very easy to reason about each block.

The rest is a matter of synchronizing these interruptions to a useful outcome, which, as stated elsewhere, CSP and modern languages integrating the primitives for that natively, make really easy.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: