Thread-Safe Programming with sync - Go Tutorial for Beginners #27
Video: Thread-Safe Programming with sync - Go Tutorial for Beginners #27 by Taught by Celeste AI - AI Coding Coach
Watch full page →Thread-Safe Programming with sync in Go
In Go, the sync package provides powerful primitives to write safe concurrent code by managing access to shared resources. Key tools include Mutex for exclusive locking, RWMutex for read-write locks, Once for one-time initialization, and Pool for efficient object reuse.
Code
package main
import (
"fmt"
"sync"
)
// Example using sync.Mutex to protect shared counter
func mutexExample() {
var mu sync.Mutex
counter := 0
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
mu.Lock() // Acquire exclusive lock
counter++ // Safely increment shared variable
mu.Unlock() // Release lock
}()
}
wg.Wait()
fmt.Println("Counter with Mutex:", counter)
}
// Example using sync.RWMutex for read-heavy workloads
func rwMutexExample() {
var rw sync.RWMutex
data := 0
var wg sync.WaitGroup
// Writer goroutine
wg.Add(1)
go func() {
defer wg.Done()
rw.Lock() // Exclusive lock for writing
data = 42
rw.Unlock()
}()
// Multiple reader goroutines
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
rw.RLock() // Shared lock for reading
fmt.Println("Reader", id, "reads", data)
rw.RUnlock()
}(i)
}
wg.Wait()
}
// Example using sync.Once for one-time initialization
var once sync.Once
var config string
func loadConfig() {
fmt.Println("Loading config...")
config = "Config data loaded"
}
func onceExample() {
for i := 0; i < 3; i++ {
go func() {
once.Do(loadConfig) // Ensures loadConfig runs only once
fmt.Println(config)
}()
}
}
// Example using sync.Pool for object reuse
func poolExample() {
var pool = sync.Pool{
New: func() interface{} {
return make([]byte, 1024) // Allocate 1KB buffer
},
}
buf := pool.Get().([]byte) // Get buffer from pool
fmt.Println("Got buffer of length", len(buf))
pool.Put(buf) // Return buffer to pool
}
func main() {
mutexExample()
rwMutexExample()
onceExample()
// Wait a moment for onceExample goroutines to finish
// (In real code, use sync.WaitGroup or other sync)
fmt.Scanln()
poolExample()
}
Key Points
sync.Mutexprovides exclusive locking to protect shared data from concurrent access.sync.RWMutexallows multiple readers or one writer, optimizing read-heavy scenarios.sync.Onceensures a function runs only once, useful for safe singleton initialization.sync.Poolenables efficient reuse of temporary objects to reduce GC overhead.- Combining these primitives helps write robust and performant concurrent Go programs.