Concurrency Patterns & sync·Q221·Medium
RWMutex allows many concurrent readers or one writer. It pays off only when reads heavily outnumber writes and the critical section is long enough that letting readers…
Concurrency Patterns & sync·Q222·Hard
Normal mode: waiters queue in FIFO order, but a woken waiter does not get the lock handed to it. It has to compete with goroutines that are arriving right now, and those…
Concurrency Patterns & sync·Q223·Hard
No. Go mutexes are not reentrant and are not tied to a goroutine. If the same goroutine calls Lock twice, it deadlocks. One goroutine may also Unlock a mutex that a…
Concurrency Patterns & sync·Q224·Medium
type Counter struct { mu sync.Mutex n int } func (c Counter) Inc() { // value receiver c.mu.Lock() defer c.mu.Unlock() c.n++ } func main() { var c Counter var wg…
Concurrency Patterns & sync·Q225·Medium
The classic bug is calling Add inside the goroutine: // BUG: Wait may run before any Add, and return immediately for _, j := range jobs { go func() { wg.Add(1) defer…
Concurrency Patterns & sync·Q226·Medium
once.Do(f) runs f exactly once, even with concurrent callers. All callers block until f returns, and the completion of f happens-before any Do returns, so callers see…
Concurrency Patterns & sync·Q227·Hard
sync.Cond lets goroutines wait for a condition on shared state that a mutex protects. Wait does three things: it atomically unlocks c.L , suspends the goroutine, and…
Concurrency Patterns & sync·Q228·Hard
sync.Pool is a cache of temporary objects, sharded per P (processor), that reduces allocation pressure. Get tries, in order: the local P's private slot, the local P's…
Concurrency Patterns & sync·Q229·Medium
The docs name two cases where sync.Map is better: A key is written once and then read many times, as in a grow-only cache. Multiple goroutines read, write and overwrite…
Concurrency Patterns & sync·Q230·Medium
Go 1.19 added atomic.Int32 , Int64 , Uint32 , Uint64 , Uintptr , Bool and Pointer[T] . They are better than the function-based API for three reasons: No accidental…
Concurrency Patterns & sync·Q231·Hard
func StoreMax(a *atomic.Int64, v int64) { for { cur := a.Load() if v <= cur { return } if a.CompareAndSwap(cur, v) { return } // another goroutine changed it: reload and…
Concurrency Patterns & sync·Q232·Hard
The memory model says when a read in one goroutine is guaranteed to see a write made in another. If a write happens-before a read and no other write intervenes, the read…
Concurrency Patterns & sync·Q233·Hard
var done bool var msg string func setup() { msg = "hello" done = true } func main() { go setup() for !done { } fmt.Println(msg) } No output is guaranteed. This is a data…
Concurrency Patterns & sync·Q234·Medium
-race (for go test , go run and go build ) instruments every memory access and synchronization operation. It uses ThreadSanitizer's happens-before algorithm, based on…
Concurrency Patterns & sync·Q235·Medium
func main() { runtime.GOMAXPROCS(1) var n int var wg sync.WaitGroup for range 1000 { wg.Go(func() { n++ }) } wg.Wait() fmt.Println(n) } It will often print 1000 with one…
Concurrency Patterns & sync·Q236·Medium
func main() { var wg sync.WaitGroup for i := 0; i < 3; i++ { wg.Add(1) go func() { defer wg.Done() fmt.Print(i, " ") }() } wg.Wait() } Go 1.22 and later (when go.mod…
Concurrency Patterns & sync·Q237·Hard
func WorkerPool[In, Out any]( ctx context.Context, workers int, in <-chan In, fn func(context.Context, In) Out, ) <-chan Out { out := make(chan Out) var wg…
Concurrency Patterns & sync·Q238·Medium
Fan-out means several goroutines read from the same input channel to spread the work. Fan-in means merging several channels into one. func Merge[T any](ctx…
Concurrency Patterns & sync·Q239·Hard
Sending to or receiving from a nil channel blocks forever. Inside a select , a case on a nil channel is therefore never chosen. Setting a channel variable to nil is the…
Concurrency Patterns & sync·Q240·Hard
func gen(ctx context.Context, nums ...int) <-chan int { out := make(chan int) go func() { defer close(out) for _, n := range nums { select { case out <- n: case…
Concurrency Patterns & sync·Q241·Medium
func fastest(ctx context.Context, mirrors []string) string { ch := make(chan string) for _, m := range mirrors { go func() { ch <- fetch(ctx, m) }() } return <-ch } Only…
Concurrency Patterns & sync·Q242·Hard
The rule is that only a sender closes a channel, and only when no other sender can still send . Sending on a closed channel panics, closing twice panics, and a receiver…
Concurrency Patterns & sync·Q243·Medium
Buffered channel as a counting semaphore , which is idiomatic and has no dependencies: sem := make(chan struct{}, 10) // at most 10 in flight var wg sync.WaitGroup for…
Concurrency Patterns & sync·Q244·Hard
golang.org/x/sync/errgroup is a WaitGroup plus error propagation plus cancellation. g.Go(f) runs f in a goroutine. g.Wait() blocks until all functions return, then…
Concurrency Patterns & sync·Q245·Hard
The core ideas: stream the input instead of loading it, bound the number of goroutines, and apply backpressure through channels. func Process(ctx context.Context, r…
Concurrency Patterns & sync·Q246·Hard
Ticker: the simplest option is a fixed interval with no bursts. t := time.NewTicker(100 * time.Millisecond) // 10 rps defer t.Stop() for _, req := range reqs { select {…
Concurrency Patterns & sync·Q247·Hard
golang.org/x/sync/singleflight deduplicates concurrent calls for the same key. While one call for a key is in flight, later callers wait for it and share its result.…
Concurrency Patterns & sync·Q248·Hard
func main() { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() var workers sync.WaitGroup jobs := make(chan Job, 100)…
Concurrency Patterns & sync·Q249·Medium
WithCancelCause (1.20): cancel(err) records why the context was cancelled, and context.Cause(ctx) returns that error while ctx.Err() is still Canceled . It makes logs…
Concurrency Patterns & sync·Q250·Medium
for { select { case msg := <-msgs: handle(msg) case <-time.After(time.Minute): // new timer every iteration log.Println("idle") } } Before Go 1.23: every iteration…
Concurrency Patterns & sync·Q251·Medium
func main() { ch := make(chan int) ch <- 1 // no receiver fmt.Println(<-ch) } It prints fatal error: all goroutines are asleep - deadlock! . The send on an unbuffered…
Concurrency Patterns & sync·Q252·Hard
Naive double-checked locking reads a shared flag or pointer without synchronization: if !initialized { // racy read: may see true before the data writes are visible…
Concurrency Patterns & sync·Q253·Medium
The proverb is guidance, not a rule. Choose by the shape of the problem . Use channels when you are: transferring ownership of data (a producer hands work to a…
Concurrency Patterns & sync·Q254·Hard
Tests built on time.Sleep are slow and flaky. testing/synctest became generally available in Go 1.25. synctest.Test(t, f) runs f in an isolated "bubble": Time is…
Concurrency Patterns & sync·Q255·Hard
func main() { defer func() { if r := recover(); r != nil { fmt.Println("recovered:", r) } }() go func() { panic("boom") }() time.Sleep(time.Second) fmt.Println("done") }…
Concurrency Patterns & sync·Q256·Hard
CPUs keep memory coherent per cache line : 64 bytes on most x86-64 CPUs, 128 bytes on some arm64 and ppc64 chips. When two cores write different variables that sit on…
Concurrency Patterns & sync·Q257·Hard
GOMAXPROCS is the number of Ps, which is the maximum number of goroutines executing Go code at the same moment. Goroutines blocked in syscalls do not count against it.…
Concurrency Patterns & sync·Q258·Hard
A channel delivers each value to one receiver, so broadcasting needs a channel per subscriber. The hard parts are slow consumers, unsubscribing without a…