Mutex 互斥鎖
- 主要有三種鎖,使用情境不太同
sync.Mutex
- 多個 goroutine 同時去讀寫某個變數會出問題,因此加上 lock,確保前一個 goroutine 操作完,下一個才能用
情境:多人同時存款
package main
import (
"fmt"
"sync"
)
type Bank struct {
balance int // 想成銀行全部餘額
}
// 存款
func (b *Bank) saveMoney(money int) {
b.balance += money
}
// 確認餘額
func (b *Bank) getBalance() int {
return b.balance
}
func main() {
var wg sync.WaitGroup
var mux sync.Mutex
wg.Add(1000)
b := Bank{}
for i := 0; i < 1000; i++ {
go func() {
mux.Lock()
b.saveMoney(1000) // 前後上鎖
mux.Unlock()
wg.Done()
}()
}
wg.Wait()
fmt.Println(b.getBalance())
}
sync.RWMutex
- 讀寫鎖 (多讀單寫),允許多個讀 concurrency,單個寫
- 寫的時候 lock,確保值是對的,讀的時候 concurrency
情境:既然可以多人同時存,那也要能多人同時讀
package main
import (
"fmt"
"sync"
)
type Bank struct {
balance int
}
// 存款
func (b *Bank) saveMoney(money int) {
b.balance += money
}
// 確認餘額
func (b *Bank) getBalance() int {
return b.balance
}
func main() {
var wg sync.WaitGroup
var mux sync.RWMutex
wg.Add(10)
b := Bank{}
for i := 0; i < 5; i++ {
go func() {
mux.Lock()
b.saveMoney(1000) // 前後上鎖
mux.Unlock()
wg.Done()
}()
}
for i := 0; i < 5; i++ {
go func() {
mux.RLock()
_ = b.getBalance() // 讀的時候並發
mux.RUnlock()
wg.Done()
}()
}
wg.Wait()
fmt.Println(b.getBalance())
}
sync.Once
- 情境:有一個 function,我們希望在 concurrency 時,只被所有 goroutine 做一次
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var once sync.Once
for i := 0; i < 10; i++ {
go func() {
once.Do(read)
}()
}
time.Sleep(time.Second)
}
func read() {
fmt.Println(1)
}