Go 中的协程同步(锁) - Go语言中文社区

Go 中的协程同步(锁)


先来看一个简单的例子,在不运行的前提下猜测结果是什么
这里模仿两个人同时刷卡的操作,猜测最后剩余多少钱

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)     // 等待程序全部执行完毕
    fmt.Println(account.Left())
}
结果为-1.

是不是感觉很费解。原因是当媳妇和自己在花钱的时候,同时抢到了相同的工资数(我们启动了2个协程),经过判断都成立,则进入sleep 1秒钟。 这时无论如何都会减去该花的钱。所以最后结果为 -1.

解决办法,为数据加锁,使其只有一人操作数据。

当然,解决的办法有很多种,这只是go里面比较好的解决办法

sync.Mutex
package main

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

type Account struct {
    flag sync.Mutex     // 使用一种复式变量, 只有一个人锁住,其他人就会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)     // 等待程序全部执行完毕
    fmt.Println(account.Left())
}

这样结果就合乎逻辑了!!!

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

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢