先來看一個簡單的例子,在不運(yùn)行的前提下猜測結(jié)果是什么
這里模仿兩個人同時刷卡的操作,猜測最后剩余多少錢
package main
import (
"time"
"fmt"
)
type Account struct {
money int
}
func (a *Account)DoPre() {
time.Sleep(time.Second) // 模仿銀行進(jìn)行檢測
}
func (a *Account)GetGongzi(n int) {
a.money += n
}
func (a *Account) GiveWife(n int) {
if a.money > n {
a.DoPre()
a.money -= n
}
}
func (a *Account)Buy(n int) {
if a.money > n {
a.DoPre()
a.money -= n
}
}
func (a *Account) Left() int {
return a.money
}
func main() {
var account Account
account.GetGongzi(10)
go account.GiveWife(6) // 媳婦花6塊
go account.Buy(5) // 同時自己花5塊
time.Sleep(2 * time.Second) // 等待程序全部執(zhí)行完畢
fmt.Println(account.Left())
}
結(jié)果為-1.
是不是感覺很費(fèi)解。原因是當(dāng)媳婦和自己在花錢的時候,同時搶到了相同的工資數(shù)(我們啟動了2個協(xié)程),經(jīng)過判斷都成立,則進(jìn)入sleep 1秒鐘。 這時無論如何都會減去該花的錢。所以最后結(jié)果為 -1.
解決辦法,為數(shù)據(jù)加鎖,使其只有一人操作數(shù)據(jù)。
當(dāng)然,解決的辦法有很多種,這只是go里面比較好的解決辦法
sync.Mutex
package main
import (
"time"
"fmt"
"sync"
)
type Account struct {
flag sync.Mutex // 使用一種復(fù)式變量, 只有一個人鎖住,其他人就會sleep 直到解鎖
money int
}
func (a *Account)DoPre() {
time.Sleep(time.Second) // 模仿銀行進(jìn)行檢測
}
func (a *Account)GetGongzi(n int) {
a.money += n
}
func (a *Account) GiveWife(n int) {
a.flag.Lock() // 鎖住
if a.money > n {
a.DoPre()
a.money -= n
}
a.flag.Unlock() // 釋放鎖
}
func (a *Account)Buy(n int) {
a.flag.Lock()
if a.money > n {
a.DoPre()
a.money -= n
}
a.flag.Unlock()
}
func (a *Account) Left() int {
return a.money
}
func main() {
var account Account
account.GetGongzi(10)
go account.GiveWife(6) // 媳婦花6塊
go account.Buy(5) // 同時自己花5塊
time.Sleep(2 * time.Second) // 等待程序全部執(zhí)行完畢
fmt.Println(account.Left())
}
這樣結(jié)果就合乎邏輯了!??!