Go 中的协程同步2 - Go语言中文社区

Go 中的协程同步2


chan同步

继续上一篇的协程同步,我们发现主程序里用了sleep等待所有任务执行完毕。这样显然不够好,那么继续寻找其它答案来解决。。。
设想,当要执行多个任务时,如果每个任务在结束时返回给调用者一个完成的信号,那么我们就可以拿着所有返回的信号,与总任务个数做对比。这样就能知道任务究竟有没有执行完毕了,于是我们就利用chan的特性解决问题

package main

import (
    "time"
    "fmt"
    "sync"
)

type Account struct {
    flag sync.Mutex     // 使用一种复用变量, 只有一个人锁住,其他人就会sleep 直到解锁
    money int
}

func (a *Account)DoPre()  {
    time.Sleep(time.Millisecond)    // 模仿银行进行检测
}

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)    // 创建专门接受信号的chan
    account.GetGongzi(10)

    go func() {
        account.GiveWife(6)
        task_chan <- 0          // 任务结束发送完成信号
    }()

    go func() {
        account.Buy(5)      
        task_chan <- 0          // 发送完成信号
    }()
    for i :=0; i <2; i++ {      // 循环接受chan数据 直到全部执行完毕
        <- task_chan
    }
    fmt.Println(account.Left())
}
waitgroup

go里面还自带了一种用于协程同步的方案,它会自动的等待任务结束,并返回相应的信号

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)    // 创建waitgroup
    wg.Add(2)    // add的个数要跟任务个数一致
    go func() {
        account.GiveWife(6)
        wg.Done()          // 任务执行完毕
    }()

    go func() {
        account.Buy(5)
        wg.Done()
    }()

    wg.Wait()      // 等待所有任务执行完毕

    fmt.Println(account.Left())
}

版权声明:本文来源简书,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://www.jianshu.com/p/1762cb13d270
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-01-12 13:08:09
  • 阅读 ( 765 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢