iTranslated by AI
Abstraction of Concurrency in Go
I came across an interesting article.
It provides a clear introduction to the differences between various programming languages, and I found the recent trends in parallel processing in Rust particularly informative as I wasn't familiar with them. However, I felt that Go required a bit more explanation, so I'm writing this supplementary article.
"Concurrency" and "Parallelism" in Go
I was originally going to write about the difference between "concurrency" and "parallelism," but it turns out it has already been thoroughly covered in this excellent article orz
...Pulling myself back together, there is a book that can be considered the bible for "concurrency" in Go.
In this book, the difference between "concurrency" and "parallelism" is described as follows (Chapter 2.1):
Concurrency is a property of the code; parallelism is a property of the running program.
Why can this be stated so definitively? It can likely be summarized by this sentence:
Concurrency and parallelism are separate for a reason: it turns out that this is a very powerful abstraction when designing your code, and Go makes the most of it.
Goroutine as a Coroutine
The keyword that comes to mind regarding abstracted concurrency is coroutine. Goroutines can be considered a type of coroutine. By the way, if you look up coroutine on Wikipedia, it says:
Coroutines are computer program components that generalize subroutines for non-preemptive multitasking, by allowing execution to be suspended and resumed. Coroutines are well-suited for implementing familiar program components such as cooperative tasks, exceptions, event loops, iterators, infinite lists and pipes.
While it is stated here that coroutines are non-preemptive, goroutines in Go have acquired preemptive asynchronous processing since 1.14 (except for some platforms).
Goroutines are now asynchronously preemptible. As a result, loops without function calls no longer potentially deadlock the scheduler or significantly delay garbage collection. This is supported on all platforms except
windows/arm,darwin/arm,js/wasm, andplan9/*.
As a result, programmers can focus on coding "concurrency" without having to worry about the implementation details of "parallelism."
Concurrency Trade-offs
Personally, I like both Go and [Rust][1], so I often think about the comparison between the two. However, seeing the "How to leverage multi-core from a multi-language perspective" article I introduced at the beginning, I feel that the two are quite contrasting when it comes to concurrency as well.
Most programming languages provide "parallelism" as part of a library or framework. Therefore, in many cases, one must design "concurrency" and "parallelism" without them being clearly differentiated. This is probably why misunderstandings occur, such as thinking of concurrency (relative to parallelism) as "executing multiple processes in order." However, from another perspective, there are performance benefits to be gained precisely because "parallelism" and "concurrency" are tightly coupled, as is the case with Rust.
On the other hand, Go comes standard with "parallelism" in its runtime, clearly separating it from "concurrency" and making them loosely coupled to increase the flexibility of "concurrency" itself. In that sense, Go and Rust are in a trade-off relationship. Well, I don't think there's such a thing as an ultimate choice like "choose either Go or Rust" (laughs).
So...
If you want to study concurrency in Go, start by reading "Concurrency in Go" first.
Reference Links
- Go: Goroutine, OS Thread and CPU Management | by Vincent Blanchon | A Journey With Go | Medium
- Go: GOMAXPROCS & Live Updates. ℹ️ This article is based on Go 1.13. | by Vincent Blanchon | A Journey With Go | Medium
- In-process caching in Go: scaling lakeFS to 100k requests/second
- Why are goroutines so lightweight? - Carpe Diem
- "Concurrency in Go" is likely a must-read for Go programmers | text.Baldanders.info
Recommended Books
Discussion