关于GoLang的concurrent map writes错误

作为一个GoLang萌新(其实就是并发编程萌新,之前一直在做PHP),对并发下共享资源的竞争了解不多。所以一开始写出了如下代码:

type OriginPriceController struct {
	OriginPriceService *origin_price_service.OriginPriceService
}
 
 
func (self *OriginPriceController) action() {
    var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		defer wg.Done()
		self.Data["product"] = self.OriginPriceService.GetOriginPriceProduct(self.C, productId)
	}()
 
	go func() {
		defer wg.Done()
		self.Data["location"] = self.OriginPriceService.GetOriginPriceLocation(self.C, locationId)
	}()
	wg.Wait()
}

轻松搞定,并行请求数据,相比之前的串行,性能基本上提升一倍。本以为并发编程也不过如此,就起几个goroutine,用WaitGroup同步多个协程间的状态,等待所有协程都执行完即可。

原本以为这样就搞定了,其实代码中隐含着一个致命问题,当多次请求测试时,很快问题就暴露出来了:

fatal error: concurrent map writes

goroutine 164 [running]:
runtime.throw(0x17e99d3, 0x15)
/usr/local/go/src/runtime/panic.go:774 +0x72 fp=0xc000069ee8 sp=0xc000069eb8 pc=0x102f6c2
runtime.mapassign_faststr(0x16fe080, 0xc000574150, 0x17e0ed5, 0x8, 0x0)
/usr/local/go/src/runtime/map_faststr.go:291 +0x3fe fp=0xc000069f50 sp=0xc000069ee8 pc=0x1014d8e
gin-frame/controllers/first_origin_price.(*FirstOriginPriceController).action.func2(0xc00029e550, 0xc00014e180, 0x571)
/Users/why/Desktop/go/gin-frame/controllers/first_origin_price/first_origin_price_controller.go:62 +0xc4 fp=0xc000069fc8 sp=0xc000069f50 pc=0x164e0d4
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1357 +0x1 fp=0xc000069fd0 sp=0xc000069fc8 pc=0x105cd81
created by gin-frame/controllers/first_origin_price.(*FirstOriginPriceController).action
/Users/why/Desktop/go/gin-frame/controllers/first_origin_price/first_origin_price_controller.go:60 +0x156
没错,就是文章题目里提到的:concurrent map writes

原来Map,对于共享变量,资源,并发写会产生竞争, 共享资源遭到破坏,解决办法是拆分成两个局部变量用于接收goroutine,在goroutine执行完之后再将结果存入公共Map,相应代码如下:

var wg sync.WaitGroup
product := make(map[string]interface{})
location := make(map[string]interface{})
wg.Add(2)
go func() {
	defer wg.Done()
	product = self.OriginPriceService.GetOriginPriceProduct(self.C, productId)
}()
 
go func() {
	defer wg.Done()
	location = self.OriginPriceService.GetOriginPriceLocation(self.C, locationId)
}()
wg.Wait()
 
self.Data["product"] = product
self.Data["location"] = location
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值