go语言并发编程

191 阅读2分钟

这是我参与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, 再次进行二路归并.......一次类推,直到最后只有一路数据,就是我们要的结果