看人好处 记人长处 帮人难处
线程安全问题
假设我要要计算一个用户的积分,为了能够尽快算出用户所有的积分数,我们开启了协程
main.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package main
import ( "fmt" "sync" "test/user" )
func main() {
newuser:= user.User{ Point: 1, }
wg := sync.WaitGroup{} wg.Add(2)
go func() { defer wg.Done()
for i:=0; i<10000; i++ { newuser.Add() } }()
go func() { defer wg.Done()
for i:=0; i<10000; i++ { newuser.Minus() } }()
wg.Wait()
point := newuser.Get()
fmt.Println(point) }
|
user/user.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package user
type User struct { Point int64 }
func (user *User) Add() { user.Point ++ }
func (user *User) Minus() { user.Point -- }
func (user *User) Get() int64 { return user.Point }
|
结果计算的用户积分每次都不一样,正常情况下应该是 1
加锁处理
user/user.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package user
import "sync"
type User struct { Point int64 lock sync.Mutex }
func (user *User) Add() { user.lock.Lock() defer user.lock.Unlock() user.Point ++ }
func (user *User) Minus() { user.lock.Lock() defer user.lock.Unlock() user.Point -- }
func (user *User) Get() int64 { return user.Point }
|
使用channel模拟锁
nain.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package main
import ( "fmt" "sync" "test/user" )
func main() {
newuser:= user.User{ Point: 1, Lock: user.NewMutex(), }
wg := sync.WaitGroup{} wg.Add(2)
go func() { defer wg.Done()
for i:=0; i<10000; i++ { newuser.Add() } }()
go func() { defer wg.Done()
for i:=0; i<10000; i++ { newuser.Minus() } }()
wg.Wait()
point := newuser.Get()
fmt.Println(point) }
|
user/user.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package user
type Mutex struct { ch chan struct{} }
func NewMutex() *Mutex { return &Mutex{ch: make(chan struct{}, 1)} }
func (this *Mutex) Lock() { this.ch <- struct{}{} }
func (this *Mutex) UnLock() { select { case <-this.ch: default: panic("unlock error") } }
type User struct { Point int64 Lock *Mutex }
func (user *User) Add() { user.Lock.Lock() defer user.Lock.UnLock() user.Point ++ }
func (user *User) Minus() { user.Lock.Lock() defer user.Lock.UnLock() user.Point -- }
func (user *User) Get() int64 { return user.Point }
|