zoukankan      html  css  js  c++  java
  • [日常] Go语言*-竞争条件习题

    package main
    import(
    	"fmt"
    	"sync"
    )
    var balance int
    func Deposit(amount int) { balance = balance + amount }
    func Balance() int { return balance }
    /*
    问题:
    1.在Alice运行期间 balance = balance + amount 这一步运算可能会被Bob中间挤占
    2.当运行到balance + amount的时候,Bob的正好赶到,然后继续运行blance=
    3.此时Bob的增加的数据会丢失
    */
    func main(){
    	var wg sync.WaitGroup
    	wg.Add(1)
    	// Alice:
    	go func() {
    		defer wg.Done()
    	    Deposit(200)                // A1
    	    fmt.Println("=", Balance()) // A2
    	}()
    	wg.Add(1)
    	// Bob:
    	go func(){
    		defer wg.Done()
    		Deposit(100)
    	}()
    	wg.Wait()
    	res:=Balance()
    	fmt.Println(res)
    }
    

      

    练习 9.1: 给gopl.io/ch9/bank1程序添加一个Withdraw(amount int)取款函数。其返回结果应该要表明事务是成功了还是因为没有足够资金失败了。这条消息会被发送给monitor的goroutine,且消息需要包含取款的额度和一个新的channel,这个新channel会被monitor goroutine来把boolean结果发回给Withdraw。

    package main
    import(
    	"fmt"
    	"sync"
    )
    var balance int
    
    var deposits = make(chan int) //存款用channel
    var balances = make(chan int) //接收余额用channel
    
    
    func Deposit(amount int) {deposits <- amount}
    func Balance() int { return <-balances }
    
    func main(){
    	go teller()
    
    	var wg sync.WaitGroup
    	wg.Add(1)
    	go func(){
    		defer wg.Done()
    		Deposit(100)
    		fmt.Println("=",Balance())
    	}()
    	wg.Add(1)
    	go func(){
    		defer wg.Done()
    		Deposit(200)
    		fmt.Println("=",Balance())
    	}()
    	wg.Add(1)
    	go func(){
    		defer wg.Done()
    		res:=Withdraw(200)
    		if !res{
    			fmt.Println("取款失败")
    		}
    	}()
    	wg.Wait()
    	b:=Balance()
    	fmt.Println(b)
    }
    /*
    解决:
    1.总余额限定在一个goroutine中,通过channel通讯
    2.channel是会阻塞同一时间的多个goroutine的
    */
    func teller() {
        var balance int //总余额限定在一个goroutine中
        for {
            select {
            case amount := <-deposits:
                balance += amount
            case balances <- balance:
            }
        }
    }
    //取款用函数
    func Withdraw(amount int)bool{
        Deposit(-amount)
        if Balance() < 0 {
            Deposit(amount)
            return false // insufficient funds
        }
        return true
    }
    

      

  • 相关阅读:
    Python OpenCV 常用操作
    Conda Cheatsheet | 速查表
    Loadrunner解决启动浏览器后页面显示空白
    26个ASP.NET常用性能优化方法
    C# Foreach用法
    体验ASP.NET MVC3 表单令牌功能!
    基于.Net(C#开发)平台的三层框架架构软件的设计与实现
    去掉浏览器中a标签的虚线
    Microsoft Dynamics CRM 4.0 序列号
    编写 Cookie
  • 原文地址:https://www.cnblogs.com/taoshihan/p/9051399.html
Copyright © 2011-2022 走看看