3 ms·
>They do explicitly yield Arguably, virtual threads also explicitly yield by calling one of the blocking methods in the JDK. This is very similar to putting al
by haxen 6y ago
>They do explicitly yield
Arguably, virtual threads also explicitly yield by calling one of the blocking methods in the JDK. This is very similar to putting all the bottom-level suspendable functions into the Kotlin standard library.
>virtual threads, which behave more like Go's goroutines or Erlang's processes.
I think this can be summarized as "Kotlin uses colored functions and Loom uses non-colored ones". This is a well-established core difference, I thought you had something else in mind with "explicit yield".
- pron 6y ago> Arguably, virtual threads also explicitly yield by calling one of the blocking methods in the JDK. There's nothing explicit here, or nothing more explicit than the ordinary platform threads you use today -- JDK operations might or might not block an OS thread. There is no way you can tell whether a call does that or not, and that behaviour can change (plus, there's forced preemption as an option). > This is a well-established core difference, I thought you had something else in mind with "explicit yield". I would say that an explicit colour for yielding qualifies as an explicit yield, and so falls under cooperative. In any event, virtual threads have neither explicit yield-sites nor special yield-site colours, hence they're non-cooperative, and they support forced preemption.
- haxen 6y agoWithout the very last point, forced preemption, they would indeed be cooperative because not calling any blocking method would make them non-cooperative. This is exactly the same as within the "colored" subspace in a language that has this distinction. As long as all the functions you call are suspendable, you equally have no idea which one will actually suspend. So, without forced preemption based on GC safepoints, and as long as there is any blocking operation left in the library, Loom qualifies as a cooperative multithreading system.
- pron 6y ago> Without the very last point, forced preemption, they would indeed be cooperative because not calling any blocking method would make them non-cooperative If user code cannot possibly know whether an operation blocks or not, then it cannot "cooperate." > As long as all the functions you call are suspendable, you equally have no idea which one will actually suspend. First, this is true hypothetically but never in practice. Consider that if code really didn't care about blocking, then why not colour everything in the blocking colour? The answer is that in the coloured mode, compilation and cost of the two colours are very different. Second, and more importantly, the reason that there are two colours is exactly to enable a cooperative style. While a "blocking" routine may or may not block, a non-blocking one never does and that is the crucial difference. With cooperative multi-tasking the default mode is that of a critical section -- there is no scheduling point unless you explicitly know in advance there might be one and where. With preemptive concurrency the default is the opposite: yielding may happen at any time unless you explicitly enter a critical section. This results in very different coding styles. Anyway, we're arguing over definitions, so you may want to consult Wikipedia's definitions [1] [2]. [1]: https://en.wikipedia.org/wiki/Cooperative_multitasking https://en.wikipedia.org/wiki/Cooperative_multitasking [2]: https://en.wikipedia.org/wiki/Preemption_(computing)#PREEMPTIVE https://en.wikipedia.org/wiki/Preemption_(computing)#PREEMPT...
- haxen 6y ago"processes voluntarily yield control periodically or when idle or logically blocked in order to enable multiple applications to be run concurrently." This tells me virtual threads (without forced preemption) are cooperative.
- pron 6y agoVirtual threads do not do it voluntarily. They have no knowledge or control over where they might yield. Without forced preemption, I guess you can say that as long as they don't call into the JDK in any way (including e.g. throwing exceptions) or any third-party library then they shouldn't normally expect to yield, but I don't count calling any code you haven't personally written "voluntarily yielding". We call them preemptive with or without forced preemption -- in line, I think, with the definitions on Wikipedia -- but whatever you choose call them, the concurrency programming style is the same as that with threads today or Go's goroutines, and is different from the style of C#/JS's async/await, Kotlin's coroutines, or more explicit async code, all of which result in user code relying on knowing where yield points (possibly) are (i.e. "critical section" by default). BTW, even with OS threads, when you run transaction-handling code, as opposed to long-running computation, time-sharing preemption is the exception rather than the rule.