这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战」
一. Go语言并发编程
- 采用了CSP(Communication Seuential process)模型
- 不需要锁, 不需要callback
- 并发编程 vs 并行计算
1.1 CSP并发模型
CSP模型是上个世纪七十年代提出的,用于描述两个独立的并发实体通过共享的通讯 channel(管道)进行通信的并发模型。 CSP中channel是第一类对象,它不关注发送消息的实体,而关注与发送消息时使用的channel。
1.2 Golang CSP
Golang 就是借用CSP模型的一些概念为之实现并发进行理论支持,其实从实际上出发,go语言并没有,完全实现了CSP模型的所有理论,仅仅是借用了 process和channel这两个概念。process是在go语言上的表现就是 goroutine 是实际并发执行的实体,每个实体之间是通过channel通讯来实现数据共享。
\
1.3 不需要锁, 不需要callback
go使用CSP模型进行通信, 不需要使用锁, 其实, 这里不需要锁指的是用户在使用go语言进行并发通信的时候不需要使用锁. 也不需要使用callback. 但是, go底层其实还是使用了锁和callback的.
\
2.1 模拟服务器启动, 打印内容到页面
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
fmt.Fprintf(writer, "<h1>Hello World %s</h1>", request.FormValue("name"))
})
http.ListenAndServe(":8888", nil)
}
这里面需要注意的是启动一个服务器的方式
2.2 主方法main和Hello world方法进行通信, 通信使用的是channel
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan string)
for i := 0; i< 5000; i++ {
go hello(i, ch)
}
for {
str := <-ch
fmt.Println(str)
}
time.Sleep(time.Millisecond)
}
func hello(i int, ch chan string) {
for {
ch <- fmt.Sprintf("hello world, %d", i)
}
}
2.3 内部排序
func main() {
arr := []int {2, 5, 1, 9, 23, 01}
sort.Ints(arr)
for i, v := range arr {
fmt.Printf("%d, %d\n", i, v)
}
}
内部排序使用的是内建函数
2.4 go实现外部排序 pipeline
我们使用外部排序的时候,会用到归并排序, 先来看看什么是归并排序?
将数据分为左右两半, 分别归并排序, 再把两个有序数据归并
上图演示了归并排序中的二路归并. 其实归并排序还可以有三路归并, N路归并
有一个大的集合, 首先将其分为两个小的集合, 使用内部排序对两个小的集合进行内部排序
得到排好序的两个集合, 然后进行归并排序
第一步: 取出两个集合的首元素. 比较, 如果一样, 取左侧元素---->1
第二步: 再次取出两个集合的首元素, 比较, 右侧小--->1
第三步: 再次取出两个集合的首元素, 比较, 左侧小--->2
........
依次类推
接下来,我们的外部排序, 采用二路归并的方式实现.
数据源,来自多方. 比如hadoop中的多个hdfs
然后将数据发送到节点1, 进行二路归并, 归并后的结果在发送到节点2, 再次进行二路归并.......一次类推,直到最后只有一路数据,就是我们要的结果