山脚人多,我们山顶见
线程安全问题
假设我要要计算一个用户的积分,为了能够尽快算出用户所有的积分数,我们开启了协程
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处理
man.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
| package main
import ( "fmt" "sync" "test/user" )
func main() {
newuser:= user.NewUser()
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 44 45 46 47 48 49 50 51 52 53
| package user
type opera func()
type User struct { Point int64 ch chan opera }
func NewUser() *User { ch := make(chan opera) user := &User{ Point: 1, ch: ch, }
go user.Watch()
return user }
func (user *User) Watch() { for fn := range user.ch { fn() } }
func (user *User) add() { user.Point ++ }
func (user *User) Add() { user.ch <- user.add }
func (user *User) minus() { user.Point -- }
func (user *User) Minus() { user.ch <- user.minus }
func (user *User) Get() int64 { return user.Point }
|