liveBook · Manning

Rwmutex

As explained in 100 Go Mistakes and How to Avoid Them

sync.RWMutex is a Go standard-library type that provides mutual exclusion with separate read and write locking modes.

A common mistake is unlocking an RWMutex after assigning a shared map to a local variable, then iterating after unlock. Map assignment copies only the map header and still aliases the same runtime data, so a concurrent write races with iteration; slices behave similarly through shared backing arrays. section 9.10

Choose the critical-section boundary according to the work performed:

  • Protect the entire read operation with RLock and defer RUnlock when iteration is short. section 9.10
  • Copy every map entry while holding RLock, unlock, and perform expensive processing on the independent copy. section 9.10
  • Validate inputs before acquiring a write lock when validation does not require protected state; this reduces lock scope and can avoid recursive locking. section 9.8.2

Formatting while holding the write lock

UpdateAge can lock the Customer, discover a negative age, and format an error containing %v and the receiver. Formatting calls Customer.String, which attempts RLock while UpdateAge already holds the write lock; the call therefore deadlocks. Validate age first, or format only unlocked fields such as the customer ID. section 9.8.2

func (c *Cache) AverageBalance() float64 {
    c.mu.RLock()
    balances := c.balances                  #1
    c.mu.RUnlock()
 
    sum := 0.
    for _, balance := range balances {      #2
        sum += balance
    }
    return sum / float64(len(balances))
}

Inspect the aliasing pattern that leaves map iteration outside the read lock. section 9.10

func (c *Cache) AverageBalance() float64 {
    c.mu.RLock()
    defer c.mu.RUnlock()       #1
 
    sum := 0.
    for _, balance := range c.balances {
        sum += balance
    }
    return sum / float64(len(c.balances))
}

Compare the minimal whole-operation lock for inexpensive iteration. section 9.10

How 100 Go Mistakes and How to Avoid Them covers it

How deep it goes
Explains lock-scope choices, map and slice aliasing, race consequences, and recursive-lock deadlocks without descending into implementation internals.
Examples
Uses a customer-balance cache, shared map and slice assignments, and a Customer whose error formatting recursively requests a read lock.
What it assumes
Assumes concurrent access and mutex fundamentals while teaching read/write lock scope, shared backing storage, and lock reentrancy hazards.
What you can do after
Diagnose/debug with the race detector, identify unsafe aliases and recursive locking, and select whole-operation locking or defensive copying.
How it connects
Connects RWMutex with mutexes, critical sections, maps, slices, data races, deadlocks, string formatting, and unit testing.

Also explained in

Compare how 4 books explain rwmutex →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Go Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.