
[日常] Go语言圣经-竞争条件习题
发布日期:2021-05-18 07:59:28
浏览次数:21
分类:精选文章
本文共 2871 字,大约阅读时间需要 9 分钟。
=Golang程序优化指南=
在设计并发程序时,确保数据安全和正确性至关重要。以下优化版本解决了原程序可能引起的数据丢失问题,并确保了程序的健壮性:
=[版本1] 取款安全 isolate financial operations in a goroutine
package mainimport ( "fmt" "sync")var balance intfunc Deposit(amount int) { // 在一个 goroutine 中限制总余额 if balance < 0 { // 如果客户的钱跑掉了,不再处理其他交易 // prevent negative balance balance = 0 } balance += amount}func Balance() int { return balance}func main() { var wg sync.WaitGroup // 告知 teller goroutine 开始一个新的交易 teller() // Alice 的操作 go func() { defer wg.Done() Deposit(200) fmt.Printf("Alice: %d\n", Balance()) }() // Bob 的操作 go func() { defer wg.Done() Deposit(100) }() // 售款操作示例 go func() { defer wg.Done() res := Withdraw(100) if !res { fmt.Printf("未能取款\n") } else { fmt.Printf("取款成功\n") } }() // 等待所有 goroutine 完成 wg.Wait() // 最终的余额检查 fmt.Printf("最终余额: %d\n", Balance())}// 新增函数:示例的取款函数func Withdraw(amount int) bool { // 尝试取款 Deposit(-amount) if Balance() < 0 { // 如果有负额,尝试恢复 Deposit(amount) return false // 没有足够的资金 } return true}// teller goroutine 用于协调所有交易func teller() { var balance int for { select { case amount := <- deposits: if balance < 0 { balance = 0 } balance += amount case balances := <- balances: // 等待余额更新 } }}
=[版本2] 优化后的代码结构
package mainimport ( "fmt" "sync")var deposits = make(chan int, 10) // 最大同时存款数量var balances = make(chan int, 10) // 最大同时查询数量func Deposit(amount int) { deposits <- amount}func Balance() int { return <-balances}func main() { var wg sync.WaitGroup // 初始化一个 teller goroutine teller() // 示例存款操作 go func() { defer wg.Done() Deposit(200) fmt.Printf("存款成功: 200\n") }() // 示例查询操作 go func() { defer wg.Done() fmt.Printf("当前余额: %d\n", Balance()) }() // 售款操作示例 go func() { defer wg.Done() res := Withdraw(100) if !res { fmt.Printf("取款失败\n") } else { fmt.Printf("取款成功\n") } }() // 等待所有操作完成 wg.Wait() // 最终检查余额 fmt.Printf("系统最终余额: %d\n", Balance())}// teller goroutine 用于处理并发交易func teller() { var balance int for { select { case amount := <- deposits: if balance < 0 { balance = 0 } balance += amount case <- balances: // 等待同时查询处理 } }}// 新增函数:实现取款功能func Withdraw(amount int) bool { // 尝试取款 Deposit(-amount) if Balance() < 0 { // 恢复资金失败,返回 false return false } return true}
以上代码结合了 channel 通讯机制,确保了在多 goroutine 环境下同时操作的安全性。 teller goroutine 用于协调余额更新,避免了不同 goroutine 比赛读取和写入问题。同时,每个 goroutine 都使用 waitgroup 进行协调,确保代码整体同步有序运行。
发表评论
最新留言
网站不错 人气很旺了 加油
[***.192.178.218]2025年04月24日 15时17分05秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
三维点云处理
2019-03-17
source insight V4 下载方法
2019-03-17
UART\串口\TTL\RS-232\RS-485的区别
2019-03-17
springboot security 基于redis的session共享(7)
2019-03-17
vue 权限管理 菜单按钮权限控制(7)
2019-03-17
vue 权限管理 主题切换(8)
2019-03-17
springboot 文件上传下载(简洁明了)
2019-03-17
spring
2019-03-17
inno setup 一些技巧
2019-03-17
Qt 在Excel文件中Chart绘图
2019-03-17
TCP 详解
2019-03-17
U3D时间
2019-03-17
U3D资源加载
2019-03-17
音频优化(简短版本)
2019-03-17
01-webpack5理解及配置
2019-03-17
JavaScript作用域和作用域链
2019-03-17
STM32F103 实例应用(6)——通信概念
2019-03-17
洛谷 P1020 导弹拦截 (LIS)
2019-03-17