分享
  1. 首页
  2. 文章

个人对于golang的goroutine并发处理任务时的理解

rfyiamcool · · 2119 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

以前用golang做并发处理的时候,很是粗暴,就是利用golang的高级性能,直接fork一个任务,来处理请求,最典型的就是直接 go func,当时是因为用http和socket没觉得什么,今天再次看golang的goroutine的时候,发现这几天写的程序有些问题。比如用goroutine的时候,同步堵塞。太快了,需要堵堵,不然我没法判断逻辑了。

原文地址,blog.xiaorui.cc

来个简单的例子:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//xiaorui.cc
package main
import(
"fmt"
"runtime"
"time"
)
varaint=1
func main(){
runtime.GOMAXPROCS(runtime.NumCPU())
go sheep(1)
//go sheep(2)
time.Sleep(time.Millisecond)
fmt.Println("end",a)
}
func sheep(iint){
for;;i+=1{
fmt.Println(i,"个屌丝")
a+=1
}
}

wKiom1MtuyqyA9WiAABz1gj0xqw874.jpg

原文:xiaorui.cc

这个是打印屌丝的数量,golang下的并发直接go 函数就可以了,但是单纯的go的话,他会因为后续的main主函数的任务结束,而结束 。 对于main来说,我已经运行完了,刚才go出去的任务,爱咋咋地。。。 他就这么不负责不管了。 其实这里咱们先不说用golang的解决的方法, 其实可以在结束的时候做个判断,比如每次go完了后,不管成功或者失败都会给一个全局变量加个数或者赋予一个值。 然后再main里面做一个判断,接着是堵塞这个判断,只有if 匹配后,才推出程序。

这个是土方法,其实咱们可以用golang自带的channel,这个东西初级的想法,可以解决上面的问题。 他在golang里面代表了通信官的作用。

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//xiaorui.cc
package main
import(
"fmt"
)
varastring
varc=make(chan int,10)
funcf(){
fmt.Println("f 函数运行了")
a="hello, world"
c<-0
}
func main(){
fmt.Println("先让f这个函数先跑着")
gof()
<-c
fmt.Println("我这里取得了a的值",a)
}

channel有四个操作:

创建:c = make(chan int)

发送:c <- 1

提取:i <- c

关闭:close(c)

里面的10是buffered channels,指定channel的缓冲大小

ch := make(chan type, value)

value == 0 !无缓冲(阻塞)

value > 0 !缓冲(非阻塞,直到value个元素)


大家可以跑跑下面的例子,加深下channel的理解 。

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package main
import(
"fmt"
"time"
)
func main(){
go say("world")
say("hello")
fmt.Println("---------------1")
a:=[]int{7,2,8,-9,4,0}
c:=make(chan int)
go sum(a[:len(a)/2],c)
go sum(a[len(a)/2:],c)
x,y:=<-c,<-c//receive fromc
fmt.Println(x,y,x+y)
fmt.Println("---------------2")
c2:=make(chan int,2)
c2<-1
c2<-2
fmt.Println(<-c2)
fmt.Println(<-c2)
fmt.Println("---------------3")
c3:=make(chan int,10)
go fibonacci(cap(c3),c3)
fori:=rangec3{
fmt.Println(i)
}
fmt.Println("---------------4")
c4:=make(chan int)
quit:=make(chan int)
go func(){
fori:=0;i<10;i++{
fmt.Println(<-c4)
}
quit<-0
}()
fibonacci2(c4,quit)
fmt.Println("---------------5")
tick:=time.Tick(100*time.Millisecond)
boom:=time.After(500*time.Millisecond)
for{
select{
case<-tick:
fmt.Println("tick. ")
case<-boom:
fmt.Println("BOOM!")
return
default:
fmt.Println(" .")
time.Sleep(50*time.Millisecond)
}
}
}
func say(sstring){
fori:=0;i<5;i++{
time.Sleep(100*time.Millisecond)
fmt.Println(s)
}
}
func sum(a[]int,cchan int){
sum:=0
for_,v:=rangea{
sum+=v
}
c<-sum//send sumtoc
}
func fibonacci(nint,cchan int){
x,y:=0,1
fori:=0;i<n;i++{
c<-x
x,y=y,x+y
}
close(c)
}
func fibonacci2(c,quit chan int){
x,y:=0,1
for{
select{
casec<-x:
x,y=y,x+y
case<-quit:
fmt.Println("quit")
return
}
}
}

对于golang的同步问题,不仅可以用channel来解决,也可以用golang的另一个包 sync来解决。

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main
import(
"fmt"
"sync"
)
func main(){
var wg sync.WaitGroup
fori:=0;i<100;i++{
wg.Add(1)
}
fori:=0;i<100;i++{
go done(&wg)
}
wg.Wait()
fmt.Println("exit")
}
func add(wg sync.WaitGroup){
wg.Add(1)
}
func done(wg*sync.WaitGroup){
wg.Done()
}

sync.WaitGroup只有3个方法,Add(),Done(),Wait()。其中Done()是Add(-1)的别名。简单的来说,使用Add()添加计数,Done()减掉一个计数,计数不为0, 阻塞Wait()的运行。

python下的gevent里面的协程机制和golang差不多的,有时间让他们对比下,看看gevent比golang的goroutine相差有多少。

遇到的问题,这个是因为本身网络就不稳定引起的,为了更友好的显示数据,需要做好更好的defer异常的处理。


有疑问加站长微信联系(非本文作者)

本文来自:峰云就她了

感谢作者:rfyiamcool

查看原文:个人对于golang的goroutine并发处理任务时的理解

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
2119 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏