Goroutines 101: A basic walkthrough
Goroutines offer a simple way to introduce concurrency into Go applications. The keyword 'go' before a function call initiates a goroutine, enabling the function to run concurrently with the rest of the program. This approach eliminates the need for creating thread objects, sizing pools, or installing libraries, making concurrency much more straightforward than in many other languages.
When a goroutine is created, it does not wait for the function to complete. Instead, the Go scheduler acknowledges the goroutine's readiness and proceeds to the subsequent line of code in the main function. This means that the main function will not wait for the goroutine to finish executing. Once the main function concludes, the entire program terminates, without waiting for any other goroutines to complete.
To address this lack of synchronization, Go provides a WaitGroup, a tool that enables a goroutine to wait for other goroutines to complete. By incrementing the counter of the WaitGroup before starting the goroutine and decrementing it upon its completion, the main function can wait for all goroutines to finish using the Wait function. The output becomes consistent across different runs, demonstrating the correct usage of WaitGroup.
Goroutines operate like OS threads but are managed and owned by the Go runtime. This ownership allows the runtime to optimize goroutine behavior according to the specific needs of Go programs, leading to performance improvements over using threads directly. For instance, Erlang and Java have implemented similar lightweight concurrency mechanisms, but they still provide multiple options for concurrency, whereas Go has adopted a single approach with the goroutine keyword.
Despite the simplicity of goroutines, the Go scheduler is complex in both structure and behavior. It must distribute goroutines across a limited number of threads, a process that will be discussed in a future article.
The runtime.GOMAXPROCS function allows the programmer to control the number of threads the runtime can run Go code on concurrently. This limit impacts the level of parallelism the program can achieve. A smaller limit may decrease parallelism but maintain concurrency, allowing multiple goroutines to exist and be runnable simultaneously.
The runtime updates the GOMAXPROCS value based on factors such as the container CPU limit or the number of logical CPUs available. The relationship between concurrency (the ability of goroutines to interleave execution) and parallelism (the requirement of at least two goroutines executing simultaneously) is an important aspect of working with goroutines.
Written by urgent.news from Lobsters's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.