美文网首页
Go 中的协程同步(锁)

Go 中的协程同步(锁)

作者: 浑浑噩噩_邋邋遢遢 | 来源:发表于2017-07-31 21:47 被阅读0次

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

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())
}

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

相关文章

  • Go 中的协程同步(锁)

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

  • Go 中的协程同步2

    chan同步 继续上一篇的协程同步,我们发现主程序里用了sleep等待所有任务执行完毕。这样显然不够好,那么继续寻...

  • 21. Go 协程

    21. Go 协程 Go 协程是什么? Go 协程是与其他函数或方法一起并发运行的函数或方法。Go 协程可以看作是...

  • Go协程介绍

    参考自《go专家编程》Go协程所实现的是M:N的线程模型,M个协程运行在N个线程中。 1. MPG模型 Go协程中...

  • Kotlin协程使用

    目录 协程的用法 协程同步异步请求与Rxjava,原生写法的区别与优势 对于协程的理解 1.协程的用法 在安卓中添...

  • go的协程并发-channel消息机制

    go的协程并发-channel消息机制 方式一 方式二 go-协程实现方案汇总

  • GO的锁和原子操作分享

    [TOC] GO的锁和原子操作分享 上次我们说到协程,我们再来回顾一下: 协程类似线程,是一种更为轻量级的调度单位...

  • 随笔33号20180930-go协程小tips

    启动一个新的协程时,协程的调用会立即返回。与函数不同,程序控制不会去等待 Go 协程执行完毕。在调用 Go 协程之...

  • Go语言协程池模型--图数据库(Neo4j)写入

    Go语言协程池

  • kotlin协程

    协程基础 轻量级线程。在一个线程中可以启动多个协程。 在协程中使用同步方式写出异步代码(协程挂起时不会阻塞线程),...

网友评论

      本文标题:Go 中的协程同步(锁)

      本文链接:https://www.haomeiwen.com/subject/mwfdlxtx.html