golang channle 管道

管道的使用介绍

现在要计算 1-N 的各个数的阶乘,并且把各个数的阶乘放入到 map 中。最后显示出来。要求使用 goroutine 完成

 

package main

import (
	"fmt"
)

var (
	mymap = make(map[int]int, 10)
)

func calc(n int) {
	res := 1

	for i := 1; i <= n; i++ {
		res *= i
	}
	mymap[n] = res
}

func main() {
	for n := 1; n < 20; n++ {
		go calc(n)
	}

	for key, val := range mymap {
		fmt.Printf("map[%d]=%d\n", key, val)
	}

}

问题1:使用goroutine时,主线程执行结束,即使协程没有执行完毕也会结束,顾map没有结果

func main() {
	for n := 1; n < 20; n++ {
		go calc(n)
	}

	time.Sleep(time.Second * 3) // 加入睡眠
	for key, val := range mymap {
		fmt.Printf("map[%d]=%d\n", key, val)
	}

}

问题2:fatal error:并发写

API server listening at: 127.0.0.1:4417
fatal error: concurrent map writes
goroutine 36 [running]:
runtime.throw(0x4e0144, 0x15)
	D:/programs/go/src/runtime/panic.go:608 +0x79 fp=0xc0000bff28 sp=0xc0000bfef8 pc=0x42e099
runtime.mapassign_fast64(0x4c2300, 0xc000072240, 0x12, 0x0)
	D:/programs/go/src/runtime/map_fast64.go:101 +0x41a fp=0xc0000bff90 sp=0xc0000bff28 pc=0x4110ea
main.calc(0x12)
	D:/go_work/src/gortoutine/1/1.go:18 +0x94 fp=0xc0000bffd8 sp=0xc0000bff90 pc=0x4aa314
runtime.goexit()
	D:/programs/go/src/runtime/asm_amd64.s:1333 +0x1 fp=0xc0000bffe0 sp=0xc0000bffd8 pc=0x456f41
created by main.main
	D:/go_work/src/gortoutine/1/1.go:23 +0x70
goroutine 1 [sleep]:
time.Sleep(0xb2d05e00)
	D:/programs/go/src/runtime/time.go:105 +0x132
main.main()
	D:/go_work/src/gortoutine/1/1.go:26 +0x8f

排查方法:在运行某个程序时如何知道是否存在资源竞争问题。 方法很简单在编译该程序时增加一个参数 -race 即可

D:\go_work>1.exe
==================
WARNING: DATA RACE
Write at 0x00c00006e240 by goroutine 7:
  runtime.mapassign_fast64()
      D:/programs/go/src/runtime/map_fast64.go:92 +0x0
  main.calc()
      D:/go_work/src/goroutine/1/1.go:18 +0x91

Previous write at 0x00c00006e240 by goroutine 6:
  runtime.mapassign_fast64()
      D:/programs/go/src/runtime/map_fast64.go:92 +0x0
  main.calc()
      D:/go_work/src/goroutine/1/1.go:18 +0x91

Goroutine 7 (running) created at:
  main.main()
      D:/go_work/src/goroutine/1/1.go:23 +0x6f

Goroutine 6 (finished) created at:
  main.main()
      D:/go_work/src/goroutine/1/1.go:23 +0x6f
==================
map[5]=120
map[6]=720
map[8]=40320
map[13]=6227020800
==================
WARNING: DATA RACE
Read at 0x00c0000b6068 by main goroutine:
  main.main()
      D:/go_work/src/goroutine/1/1.go:27 +0x103

Previous write at 0x00c0000b6068 by goroutine 19:
  main.calc()
      D:/go_work/src/goroutine/1/1.go:18 +0xa6

Goroutine 19 (finished) created at:
  main.main()
      D:/go_work/src/goroutine/1/1.go:23 +0x6f
==================
map[14]=87178291200
map[4]=24
map[10]=3628800
map[16]=20922789888000
map[18]=6402373705728000
map[17]=355687428096000
map[19]=121645100408832000
map[1]=1
map[2]=2
map[7]=5040
map[11]=39916800
map[12]=479001600
map[15]=1307674368000
map[3]=6
map[9]=362880
Found 2 data race(s)

会提示存在两个数据竞争

低水平解决方法,给变量加锁。

package main

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

var (
	mymap = make(map[int]int, 10)
	lock  sync.Mutex
)

func calc(n int) {
	res := 1

	for i := 1; i <= n; i++ {
		res *= i
	}
	lock.Lock()
	mymap[n] = res
	lock.Unlock()
}

func main() {
	for n := 1; n < 20; n++ {
		go calc(n)
	}

	time.Sleep(time.Second * 10)
	for key, val := range mymap {
		lock.Lock()
		fmt.Printf("map[%d]=%d\n", key, val)
		lock.Unlock()
	}

}

这是个笨方法,大大影响程序性能

 

转载于:https://www.cnblogs.com/LC161616/p/10056119.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值