先來看一個簡單的例子,在不運行的前提下猜測結(jié)果是什么
這里模仿兩個人同時刷卡的操作凰兑,猜測最后剩余多少錢
package main
import (
"time"
"fmt"
)
type Account struct {
money int
}
func (a *Account)DoPre() {
time.Sleep(time.Second) // 模仿銀行進行檢測
}
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.
是不是感覺很費解似舵。原因是當媳婦和自己在花錢的時候辩涝,同時搶到了相同的工資數(shù)(我們啟動了2個協(xié)程),經(jīng)過判斷都成立新蟆,則進入sleep 1秒鐘觅赊。 這時無論如何都會減去該花的錢。所以最后結(jié)果為 -1.
解決辦法琼稻,為數(shù)據(jù)加鎖吮螺,使其只有一人操作數(shù)據(jù)。
當然帕翻,解決的辦法有很多種鸠补,這只是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) // 模仿銀行進行檢測
}
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é)果就合乎邏輯了W涎摇!睬塌!