Go语言并发编程

Go语言并发编程

  • 采用CSP(Communication Sequential Process)模型
  • 编程时不需要锁,不需要callback
  • 适合分布式

(〇)Go运行时调度机制


(一)并发版Hello World

Go并发编程的核心就是gochan,也即Goroutine和通道。

  1. 创建helloworldconc目录,创建conc.go
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
package main
//Go语言中package后的目录名可以和实际目录不一致,main表明该文件是个可执行文件

import(
"fmt"
)

func main() {
//:=变量声明,并赋初值
ch := make(chan string) //定义管道

for i := 0; i < 5; i++ {
//通过go关键字可以开启一个Goroutine
go printHelloWorld(i, ch)
}

//从通道获取消息
for {
msg := <- ch
fmt.Println(msg)
}

}

func printHelloWorld(i int, ch chan string) {
for {
//如果使用了像%d一样的format参数,就需要用到Printf,不能用Println
ch <- fmt.Sprintf("Hello World from Goroutine %d\n", i) //将字符串送入管道
}
}
  1. go run conc.go,不断循环输出:
1
2
3
4
5
Hello World from Goroutine 3
Hello World from Goroutine 4
Hello World from Goroutine 1
Hello World from Goroutine 2
Hello World from Goroutine 0

(二)并行计算

  1. 新建目录pipeline
  2. 创建nodes.go,不包括main函数:
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
package pipeline

import "sort"

///...表示可变长参数
//<-表明这个返回的通道是只出不进的
func ArraySource(a ...int) <-chan int {
//创建通道
out := make(chan int)

//创建Goroutine,将数组中的元素输送到通道
go func() {
for _, v := range a {
out <- v
}
//关闭通道
close(out)
}()

return out
}

//排序单个通道
func InMemSort(in <-chan int) <-chan int {
out := make(chan int)
go func() {
a := []int{}
//将输入通道中的数据加入切片中
for v := range in {
a = append(a, v)
}
//排序
sort.Ints(a)
//输出
for _, v := range a {
out <- v
}
//关闭通道
close(out)
}()
return out
}

//归并
func Merge(in1, in2 <-chan int) <-chan int {
out := make(chan int)
go func() {
v1, ok1 := <-in1
v2, ok2 := <-in2
for ok1 || ok2 {
if !ok2 || (ok1 && v1 <= v2) {
out <- v1
v1, ok1 = <-in1
} else {
out <- v2
v2, ok2 = <-in2
}
}
close(out)
}()
return out
}
  1. 创建可执行文件main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

func main() {
p := pipeline.Merge(
pipeline.InMemSort(pipeline.ArraySource(3, 2, 6, 7, 4)),
pipeline.InMemSort(pipeline.ArraySource(7, 4, 0, 3, 2, 8, 13)))
for {
//通过if子句,从通道获取数组元素
if num, ok := <- p; ok {
fmt.Println(num)
} else {
break
}
//等价于:
// for v := range p {
// fmt.Println(v)
// }

}
}
  1. 输出:
1
2
3
4
5
6
7
8
9
10
11
12
0
2
2
3
3
4
4
6
7
7
8
13
-------------本文结束感谢您的阅读-------------

本文标题:Go语言并发编程

文章作者:DragonBaby308

发布时间:2019年11月22日 - 22:48

最后更新:2019年12月04日 - 23:36

原始链接:http://www.dragonbaby308.com/goroutine/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

急事可以使用右下角的DaoVoice,我绑定了微信会立即回复,否则还是推荐Valine留言喔( ఠൠఠ )ノ
0%