





















































Hi ,
Welcome to a brand new issue of ProgrammingPro.
In today’sExpert Insight, we bring you an excerpt from the recently published book, Go Recipes for Developers, which demonstrates how to manage shared memory in Go by avoiding memory races and using mutexes to synchronize access to shared variables, instead of relying solely on channels.
News Highlights: 10 AI tools gain new features, including Amazon Q’s code validation; a malicious Go package evades detection for years; Stack Exchange tests AI answers despite a past ban; and Java updates JDK, frameworks, and tooling.
My top 5 picks from today’s learning resources:
But there’s more, so dive right in.
Stay Awesome!
Divya Anne Selvaraj
Editor-in-Chief
synchronized
keyword works at the bytecode level, detailing monitorenter
and monitorexit
instructions, object monitors, and how synchronized methods differ from synchronized blocks.libc
crate to access low-level kernel services, with examples on file I/O, handling processes via fork()
, and more.UIColor
.Here’s an excerpt from “Chapter 7: Concurrency" in the book, Go Recipes for Developers, by Burak Serdar, published in December 2024.
One of the most famous Go idioms is: “Do not communicate by sharing memory, share memory by communicating.” Channels are for sharing memory by communicating. Communicating by sharing memory is done using shared variables in multiple goroutines. Even though it is
discouraged, there are many use cases where shared memory makes more sense than a channel. If at least one of the goroutines updates a shared variable that is read by other goroutines, you have to ensure that there are no memory races.
A memory race happens when a goroutine updates a variable concurrently while another goroutine reads from it or writes to it. When this happens, there is no guarantee that the update to that variable will be seen by other goroutines. A famous example of this situation is thebusy-wait
loop:
func main() {
done:=false
go func() {
// Wait while done==false
for !done {}
fmt.Println("Done is true now")
}()
done=true
// Wait indefinitely
select{}
}
This program has a memory race. Thedone=true
assignment is concurrent with thefor !done
loop. That means, even though the main goroutine runsdone=true
, the goroutine readingdone
may never see that update, staying in thefor
loop indefinitely.
The Go memory model guarantees that the effect of a variable write is visible to instructions that come after that write within that goroutine only. That is, if you update a shared variable, you have to use special tools to make that update visible to other goroutines. A simple way to ensure this is to use a mutex. Mutex stands for “mutual exclusion.” A mutex is a tool you can use to ensurethe following:
In this recipe, we show how thisis done.
The section of a program that updates shared variables is a “critical section.” You use a mutex to ensure that only a single goroutine can enter itscritical section.
Declare a mutex to protect acritical section:
// cacheMutex will be used to protect access to cache
var cacheMutex sync.Mutex
var cache map[string]any = map[string]any{}
A mutex protects a set of shared variables. For instance, if you have goroutines that update a single integer, you declare a mutex for the critical sections that update that integer. You must use the same mutex every time you read or write thatinteger value.
When updating the shared variable(s), first lock the mutex. Then perform the update and unlockthe mutex:
cacheMutex.Lock()
cache[key]=value
cacheMutex.Unlock()
With this pattern, if multiple goroutines attempt to updatecache
, they will queue atcacheMutex.Lock()
and only one will be allowed. When that goroutine performs the update, it will callcacheMutex.Unlock()
, which will enable one of the waiting goroutines to acquire the lock and update thecache again.
When reading the shared variable, first lock the mutex. Then perform the read, and then unlockthe mutex:
cacheMutex.Lock()
cachedValue, cached := cache[key]
cacheMutex.Unlock()
if cached {
// Value found in cache
}
Go Recipes for Developerswas published in December 2024. Packt library subscribers can continue reading the entire book for free or you can buy the book here!
That’s all for today.
We have an entire range of newsletters with focused content for tech pros. Subscribe to the ones you find the most usefulhere.
If your company is interested in reaching an audience of developers, software engineers, and tech decision makers, you may want toadvertise with us.
If you have any suggestions or feedback, or would like us to find you a learning resource on a particular subject, just respond to this email!