Live data from Hacker News

Asynchrony is not concurrency

kristoff.it

161–170 of 228 posts

Re: Asynchrony is not concurrency

#161
post #86

Earlier quoted context omitted.

Can you give an example?

Locks, scheduling,... That introduce some synchronicity and so some kind of order. But it's enforced on the system and not a required mechanism.

But if I run "ls" on a machine, and another user runs "ls" on the same machine, wouldn't you consider them independent, even though the OS uses all kinds of locks and what not under the hood?

Re: Asynchrony is not concurrency

#162
post #157

Defining async is hard. And I'm writing this as one of the many people who designed async in JavaScript. I don't quite agree with the definition in this post: just because it's async doesn't mean that it's correct. You can get all sorts of user-land race conditions with async code, whether it uses `async`/`await` (in languages that need/support it) or not. My latest formulation (and I think that it still needs work)…

I am not deep into the matter but I would have given the answer: Async code is making code that would have been blocking non-blocking in a manner other stuff can still happen while it is being completed.

Since I work a lot in embedded loops where long running blocking snippets could literally break your I/O, lead to visible/audible dropouts etc. this would be the obvious answer.

Re: Asynchrony is not concurrency

#163
post #162
post #157

Defining async is hard. And I'm writing this as one of the many people who designed async in JavaScript. I don't quite agree with the definition in this post: just because it's async doesn't mean that it's correct. You can get all sorts of user-land race conditions with async code, whether it uses `async`/`await` (in languages that need/support it) or not. My latest formulation (and I think that it still needs work)…

I am not deep into the matter but I would have given the answer: Async code is making code that would have been blocking non-blocking in a manner other stuff can still happen while it is being completed. Since I work a lot in embedded loops where long running blocking snippets could literally break your I/O, lead to visible/audible dropouts etc. this would be the obvious answer.

But that's the thing: async, by itself, doesn't guarantee that anything is non-blocking. For your fiber (or any other kind of user-land abstraction) to be non-blocking, you MUST ensure that it doesn't perform any blocking call.

All async does is give you (some of) the tools to make code non-blocking.

Re: Asynchrony is not concurrency

#164
post #87

"Asynchrony" is a very bad word for this and we already have a very well-defined mathematical one: commutativity. Some operations are commutative (order does not matter: addition, multiplication, etc.), while others are non-commutative (order does matter: subtraction, division, etc.). try io.asyncConcurrent(Server.accept, .{server, io}); io.async(Cient.connect, .{client, io}); Usually, ordering of operations in code…

> So, my gut tells me this would be better achieved with the (shudder) `.then(...)` paradigm. It sucks, but better the devil you know than the devil you don't. The whole idea behind `await` is to make the old intuition work without the ugliness of `.then()`. `f(); await g(); h()` has exactly the expected execution ordering.

Can confirm.

In JS, we designed `await` specifically to hide `.then()`, just as we had designed `.then()` because callbacks made tracking control flow (in particular errors) too complex.

Re: Asynchrony is not concurrency

#165

So "cooperative multitasking is not preemptive multitasking". The typical use of the word "asynchronous" means that the _language is single-threaded_ with cooperative multitasking (yield points) and event based, and external computations may run concurrently, instead of blocking, and will report result(s) as events. There is no point in having asynchrony in a multithreaded or concurrent execution model, you can use b…

While this is indeed the most common use, I'll bring as counter-examples Rust (or C#, or F#, or OCaml 5+) that supports both OS threads and async. OS threads are good for CPU-bound tasks, async for IO-bound tasks.

The main benefit of having async (or Go-style M:N scheduling) is that you can afford to launch as many tasks/fibers/goroutines/... as you want, as long as you have RAM. If you're using OS threads, you need to pool them responsively to avoid choking your CPU with context-switches, running out of OS threads, running out of RAM, etc. – hardly impossible, but if you're doing more than just I/O, you can run into interesting deadlocks.

Re: Asynchrony is not concurrency

#166
post #141
post #87

"Asynchrony" is a very bad word for this and we already have a very well-defined mathematical one: commutativity. Some operations are commutative (order does not matter: addition, multiplication, etc.), while others are non-commutative (order does matter: subtraction, division, etc.). try io.asyncConcurrent(Server.accept, .{server, io}); io.async(Cient.connect, .{client, io}); Usually, ordering of operations in code…

> As written, `asyncConcurrent(...)` is confusing as shit, and unless you memorize this blog post, you'll have no idea what this code means. I get that Zig (like Rust, which I really like fwiw) is trying all kinds of new hipster things, but half the time they just end up being unintuitive and confusing. Either implement (async-based) commutativity/operation ordering somehow (like Rust's lifetimes maybe?) or just use…

I'm not sure they are that different, you could just as well store function calls in some constant each on its line then addition the result on a third. This is only syntax, not conceptual difference here. And on practical level, the difference is that the operator can be directly matched with some machine instruction, with operands being native data type such as integer.

Still, you might then prefer a word as permutability, or swappability.

Re: Asynchrony is not concurrency

#167
post #164

Earlier quoted context omitted.

> So, my gut tells me this would be better achieved with the (shudder) `.then(...)` paradigm. It sucks, but better the devil you know than the devil you don't. The whole idea behind `await` is to make the old intuition work without the ugliness of `.then()`. `f(); await g(); h()` has exactly the expected execution ordering.

Can confirm. In JS, we designed `await` specifically to hide `.then()`, just as we had designed `.then()` because callbacks made tracking control flow (in particular errors) too complex.

How is that any better to have await? Any resources I might consult on this?

Re: Asynchrony is not concurrency

#168
post #157

Defining async is hard. And I'm writing this as one of the many people who designed async in JavaScript. I don't quite agree with the definition in this post: just because it's async doesn't mean that it's correct. You can get all sorts of user-land race conditions with async code, whether it uses `async`/`await` (in languages that need/support it) or not. My latest formulation (and I think that it still needs work)…

The important thing to me is to distinguish between the abstract concept of asynchronism and how it can be implemented, and by the latter I mean both at the abstract level of a programming language and by technical coordination means in a machine. For the abstract concept at the highest level, well, it is just the dual of synchronism: two (or more) parties that somehow need to work together (i.e., one has a dependency on the other in a way that certain things need to happen before another one can continue) are not synchronized, meaning that it is not known or not defined when the things that need to happen after something else will be done. Seen that way, this definition is not hard. The hard thing can be the abstract means designed in a language: the amount of cognitive effort it takes in order to comprehended them and/or use them (in an fault-free way).

Re: Asynchrony is not concurrency

#169
post #98
post #97

Earlier quoted context omitted.

Strictly speaking commutativity is defined over (binary) operations - so if one were to say that two async statements (e.g. connect/accept) are commutative, I would have to ask, "under what operation?" Currently my best answer for this is the bind (>>=) operator (including, incidentally, one of its instances, `.then(...)`), but this is just fuzzy intuition if anything at all.

Commutative operations (all of them I think?) are trivially generalized to n-ary operations (in fact, we do this via ∑ and ∏, in the case of addition and multiplication, respectively). You're right that the question of what "operation" we're dealing with here is a bit hazy; but I'd wager that it's probably in the family of the increment operation (N++ === N + 1 = 1 + N) since we're constantly evaluating the next line…

Implication sounds right. With no further analysis, running each line in order is correct (for whatever "order" is defined by a language, let's assume imperative).

A compiler could recognise that e.g. L_2 doesn't depend on L_1, and would be free to reorder them. And compilers do recognise this in terms of data dependence of operations.

Re: Asynchrony is not concurrency

#170
post #163
post #162

Earlier quoted context omitted.

I am not deep into the matter but I would have given the answer: Async code is making code that would have been blocking non-blocking in a manner other stuff can still happen while it is being completed. Since I work a lot in embedded loops where long running blocking snippets could literally break your I/O, lead to visible/audible dropouts etc. this would be the obvious answer.

But that's the thing: async, by itself, doesn't guarantee that anything is non-blocking. For your fiber (or any other kind of user-land abstraction) to be non-blocking, you MUST ensure that it doesn't perform any blocking call. All async does is give you (some of) the tools to make code non-blocking.

Yeah, sure I mean in embedded-land any async snippet could perform any number of things, like firing a delay command that puts the whole processor to sleep.

This could potentially be avoided by clever enough compilers or runtimes, but I am not sure whether that would really be benefitial.

I am a fan of making things explicit, so the closer peoples idea of what aync is and what it isn't matches reality the better. Alternatively we should get the definition of what async should be clear first and then make the adjustment to the abstractions so they give us the guarantees people would natuarally assume come with that.

Post reply on HN