Performance gains with goroutines
Waiting for Stragglers
Extending the length of the Sleep
command in the main program and hoping for good luck that all the underlings have finished their work in the meantime is obviously not a good solution. If the computer is busy with costly operations in other processes in the meantime, it is possible that the duration will extend to a few seconds, and the race is on again.
For every goroutine to have a guaranteed outcome, the main program and the routines have to communicate. At the end of the program flow, the main program has to wait until each routine has successfully completed before it can shut down the main process. In the form of the sync
package, Go offers some tools based on semaphores that do this job reliably.
The most elegant method, preferred by Go programmers, however, uses channels. These communication lines, reminiscent of Unix pipes, transport information from one part of the program to another. In addition, they block the program flow in a routine if nothing can be fed into the channel or read out from it temporarily and are thus ideal for synchronization, because individual program parts can wait for each other.
Channels, Synchronize!
Listing 4 fires off three different goroutines again, but doesn't output anything directly in them. Instead, the goroutines feed their output, which contains data of the string
type, into a channel named done
defined in line 5. The inverted arrow <-
pointing from the data to be written (e.g., "a"
) to the channel sends the data into the channel (Figure 3).
Listing 4
gochannel.go
01 package main 02 import "fmt" 03 04 func main() { 05 done := make(chan string) 06 07 go func() { done <- "a" }() 08 go func() { done <- "b" }() 09 go func() { done <- "c" }() 10 11 defer close(done) 12 13 for i := 0; i <= 2; i++ { 14 msg := <-done 15 fmt.Println(msg) 16 } 17 }
Depending on the free capacity in the channel, this is done either immediately, or the Go runtime blocks the execution of the respective goroutine until the channel can receive the data. It is very important that while one goroutine might block at any given time, other goroutines in the system continue to run unhindered and thus do not cause a hiccup in the program, but instead empower a high-performance system.
The output from Listing 4 is also non-deterministic, whether you will see abc or cba or bac is uncertain, because the single goroutines in this simple implementation don't coordinate their work with each other, and the main program only waits until all routines are finished – the order thus is rather random. What is guaranteed, though, is that the output will always contain three letters, which is an improvement over the previous race condition.
After firing off the goroutines, the main program uses the defer
statement in line 11 to stipulate that the done
channel will be closed after the program terminates; it then enters a for
loop, which uses the read operator <-
on the left (!) side of the channel variable to fetch the next value that exists in the channel in line 14 and assigns it to the msg
variable.
Synchronization with the previously spawned goroutines also occurs during this read operation. When the main program reaches the for
loop and the read operation for the first time, it is highly unlikely that any of the goroutines have had an opportunity to execute their write statements thus far. But this doesn't matter; if the channel is still empty, the program blocks in line 14 until data becomes available and the Go runtime lets one of the goroutines loose to perform its task. As soon as the first chunk of data has trickled in, the blocked read statement in the main program also notices that things are happening, obtains the available data, and the for
loop goes into the next round.
Precise Count
Now it becomes clear why, in this simple implementation, the for
loop in line 13 needs to know exactly how many data packages were fed into the channel by the goroutines in order to retrieve precisely that number. If the main program were simply to continue to ask the channel for data, the Go runtime would block the fourth read process for an infinite period of time, because no further data would be written to the channel from this point onward. A hanging main program would be the result.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Canonical Bumps LTS Support to 12 years
If you're worried that your Ubuntu LTS release won't be supported long enough to last, Canonical has a surprise for you in the form of 12 years of security coverage.
-
Fedora 40 Beta Released Soon
With the official release of Fedora 40 coming in April, it's almost time to download the beta and see what's new.
-
New Pentesting Distribution to Compete with Kali Linux
SnoopGod is now available for your testing needs
-
Juno Computers Launches Another Linux Laptop
If you're looking for a powerhouse laptop that runs Ubuntu, the Juno Computers Neptune 17 v6 should be on your radar.
-
ZorinOS 17.1 Released, Includes Improved Windows App Support
If you need or desire to run Windows applications on Linux, there's one distribution intent on making that easier for you and its new release further improves that feature.
-
Linux Market Share Surpasses 4% for the First Time
Look out Windows and macOS, Linux is on the rise and has even topped ChromeOS to become the fourth most widely used OS around the globe.
-
KDE’s Plasma 6 Officially Available
KDE’s Plasma 6.0 "Megarelease" has happened, and it's brimming with new features, polish, and performance.
-
Latest Version of Tails Unleashed
Tails 6.0 is based on Debian 12 and includes GNOME 43.
-
KDE Announces New Slimbook V with Plenty of Power and KDE’s Plasma 6
If you're a fan of KDE Plasma, you'll be thrilled to hear they've announced a new Slimbook with an AMD CPU and the latest version of KDE Plasma desktop.
-
Monthly Sponsorship Includes Early Access to elementary OS 8
If you want to get a glimpse of what's in the pipeline for elementary OS 8, just set up a monthly sponsorship to help fund its continued existence.