GO mutex -pt2
RW MUTEX
The standard library also exposes a sync.RWMutex.
By using a sync.RWMutex
, our program becomes more efficient. We can have as many readLoop()
threads as we want, while still ensuring that the writers have exclusive access.
In addition to these methods:
the sync.RWmutex
also has these methods:
Thesync.RWmutex
can help withperformance if we have aread-intensive process. Manygoroutines can safely read from the map at the same time (multiple R
Lo
ck()
calls can happen simultaneously). However, only one goroutine can hold a Lock()
and all RLock()
's will also be excluded.
package main
import (
"fmt"
"sort"
"sync"
"time"
)
type safeCounter struct {
counts map[string]int
mu *sync.RWMutex
}
func (sc safeCounter) inc(key string) {
sc.mu.Lock()
defer sc.mu.Unlock()
sc.slowIncrement(key)
}
func (sc safeCounter) val(key string) int {
sc.mu.RLock()
defer sc.mu.RUnlock()
return sc.counts[key]
}
// don't touch below this line
func (sc safeCounter) slowIncrement(key string) {
tempCounter := sc.counts[key]
time.Sleep(time.Microsecond)
tempCounter++
sc.counts[key] = tempCounter
}
type emailTest struct {
email string
count int
}
func test(sc safeCounter, emailTests []emailTest) {
emails := make(map[string]struct{})
var wg sync.WaitGroup
for _, emailT := range emailTests {
emails[emailT.email] = struct{}{}
for i := 0; i < emailT.count; i++ {
wg.Add(1)
go func(emailT emailTest) {
sc.inc(emailT.email)
wg.Done()
}(emailT)
}
}
wg.Wait()
emailsSorted := make([]string, 0, len(emails))
for email := range emails {
emailsSorted = append(emailsSorted, email)
}
sort.Strings(emailsSorted)
sc.mu.RLock()
defer sc.mu.RUnlock()
for _, email := range emailsSorted {
fmt.Printf("Email: %s has %d emails\n", email, sc.val(email))
}
fmt.Println("=====================================")
}
func main() {
sc := safeCounter{
counts: make(map[string]int),
mu: &sync.RWMutex{},
}
test(sc, []emailTest{
{
email: "john@example.com",
count: 23,
},
{
email: "john@example.com",
count: 29,
},
{
email: "jill@example.com",
count: 31,
},
{
email: "jill@example.com",
count: 67,
},
})
test(sc, []emailTest{
{
email: "kaden@example.com",
count: 23,
},
{
email: "george@example.com",
count: 126,
},
{
email: "kaden@example.com",
count: 31,
},
{
email: "george@example.com",
count: 453,
},
})
}