chan同步
繼續(xù)上一篇的協(xié)程同步嗅回,我們發(fā)現(xiàn)主程序里用了sleep等待所有任務(wù)執(zhí)行完畢及穗。這樣顯然不夠好,那么繼續(xù)尋找其它答案來(lái)解決绵载。埂陆。苛白。
設(shè)想,當(dāng)要執(zhí)行多個(gè)任務(wù)時(shí)焚虱,如果每個(gè)任務(wù)在結(jié)束時(shí)返回給調(diào)用者一個(gè)完成的信號(hào)购裙,那么我們就可以拿著所有返回的信號(hào),與總?cè)蝿?wù)個(gè)數(shù)做對(duì)比鹃栽。這樣就能知道任務(wù)究竟有沒(méi)有執(zhí)行完畢了躏率,于是我們就利用chan的特性解決問(wèn)題
package main
import (
"time"
"fmt"
"sync"
)
type Account struct {
flag sync.Mutex // 使用一種復(fù)用變量, 只有一個(gè)人鎖住民鼓,其他人就會(huì)sleep 直到解鎖
money int
}
func (a *Account)DoPre() {
time.Sleep(time.Millisecond) // 模仿銀行進(jìn)行檢測(cè)
}
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
task_chan := make(chan int) // 創(chuàng)建專門接受信號(hào)的chan
account.GetGongzi(10)
go func() {
account.GiveWife(6)
task_chan <- 0 // 任務(wù)結(jié)束發(fā)送完成信號(hào)
}()
go func() {
account.Buy(5)
task_chan <- 0 // 發(fā)送完成信號(hào)
}()
for i :=0; i <2; i++ { // 循環(huán)接受chan數(shù)據(jù) 直到全部執(zhí)行完畢
<- task_chan
}
fmt.Println(account.Left())
}
waitgroup
go里面還自帶了一種用于協(xié)程同步的方案薇芝,它會(huì)自動(dòng)的等待任務(wù)結(jié)束,并返回相應(yīng)的信號(hào)
package main
import (
"time"
"fmt"
"sync"
)
type Accout struct {
lock sync.Locker
money int
}
func (a *Accout) DoPrepare() {
time.Sleep(time.Second)
}
func (a *Accout) GetGongZi(n int) {
a.money += n
}
func (a *Accout) GiveWife(n int) {
a.lock.Lock()
if a.money > n{
a.money -= n
}
a.lock.Unlock()
}
func (a *Accout) Buy(n int) {
a.lock.Lock()
if a.money > n{
a.money -= n
}
a.lock.Unlock()
}
func (a *Accout) Left() int {
return a.money
}
func main() {
var account Accout
account.GetGongZi(10)
wg := new(sync.WaitGroup) // 創(chuàng)建waitgroup
wg.Add(2) // add的個(gè)數(shù)要跟任務(wù)個(gè)數(shù)一致
go func() {
account.GiveWife(6)
wg.Done() // 任務(wù)執(zhí)行完畢
}()
go func() {
account.Buy(5)
wg.Done()
}()
wg.Wait() // 等待所有任務(wù)執(zhí)行完畢
fmt.Println(account.Left())
}