100-go-mistakes/09-concurrency-practice/72-cond/main.go
2021-12-27 15:57:20 +01:00

98 lines
1.5 KiB
Go

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()
}
}