package main import ( "fmt" "sync" "time" ) func listing1() { type Donation struct { mu sync.RWMutex balance int } donation := &Donation{} // Listener goroutines f := func(goal int) { donation.mu.RLock() for donation.balance < goal { donation.mu.RUnlock() donation.mu.RLock() } fmt.Printf("$%d goal reached\n", donation.balance) donation.mu.RUnlock() } go f(10) go f(15) // Updater goroutine go func() { for { time.Sleep(time.Second) donation.mu.Lock() donation.balance++ donation.mu.Unlock() } }() } func listing2() { type Donation struct { balance int ch chan int } donation := &Donation{ch: make(chan int)} // Listener goroutines f := func(goal int) { for balance := range donation.ch { if balance >= goal { fmt.Printf("$%d goal reached\n", balance) return } } } go f(10) go f(15) // Updater goroutine for { time.Sleep(time.Second) donation.balance++ donation.ch <- donation.balance } } func listing3() { type Donation struct { cond *sync.Cond balance int } donation := &Donation{ cond: sync.NewCond(&sync.Mutex{}), } // Listener goroutines f := func(goal int) { donation.cond.L.Lock() for donation.balance < goal { donation.cond.Wait() } fmt.Printf("%d$ goal reached\n", donation.balance) donation.cond.L.Unlock() } go f(10) go f(15) // Updater goroutine for { time.Sleep(time.Second) donation.cond.L.Lock() donation.balance++ donation.cond.L.Unlock() donation.cond.Broadcast() } }