bc's club

This is Bc's club

Golang GMP简介

当我们需要处理大规模数据并发任务时,Golang 是一个不错的选择。Golang 在标准库中提供了一种称为 GMP(Goroutine、Channel、Mutex、Package)的并发编程模型,是 Golang 强大的并发编程能力的核心。本文将为您介绍 Golang 中的 GMP 并发编程模型。

Goroutine#

Goroutine 是 Golang 中的轻量级线程,由 Go 运行时(Go runtime)管理。Goroutine 能够并发执行,通过 go 关键字来创建。Goroutine 的启动和销毁开销很小,可以轻松地创建大量的 Goroutine。

以下是一个使用 Goroutine 的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
"fmt"
"time"
)

func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}

func main() {
go say("world")
say("hello")
}

在上面的例子中,我们创建了两个 Goroutine:say("world")say("hello")。它们会同时运行,打印出 “hello” 和 “world”,直到 say("hello") 执行完毕。

Channel#

Channel 是 Golang 中用于 Goroutine 之间通信的机制。Channel 可以被用来在 Goroutine 之间传递数据,避免了竞态条件和锁的使用。

以下是一个使用 Channel 的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import "fmt"

func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum
}

func main() {
s := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
x, y := <-c, <-c
fmt.Println(x, y, x+y)
}

在上面的例子中,我们创建了两个 Goroutine:sum(s[:len(s)/2], c)sum(s[len(s)/2:], c)。它们会同时运行,将数组的一半加起来,并将结果传递到 Channel 中。在主函数中,我们通过 <-c 从 Channel 中获取结果,并将两个结果相加。

Mutex#

Mutex 是 Golang 中用于多个 Goroutine 访问共享资源的机制。Mutex 可以确保同一时间只有一个 Goroutine 能够访问共享资源。

以下是一个使用 Mutex 的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import (
"fmt"
"sync"
)

var (
sum int
mutex sync.Mutex
)

func add(i int) {
mutex.Lock()
sum += i
mutex.Unlock()
}

func main() {
for i := 0; i < 1000; i++ {
go add(i)
}
fmt.Println(sum)
}

在上面的例子中,我们创建了 1000 个 Goroutine,每个 Goroutine 都会将一个数加到 sum 中。为了确保多个 Goroutine 不会同时访问 sum,我们使用 Mutex 来锁定 sum,以确保同一时间只有一个 Goroutine 能够访问 sum

Package#

Package 是 Golang 中用于组织代码的机制。Golang 的标准库提供了大量的 Package,例如 io、net、http 等。我们也可以自己编写 Package 来组织自己的代码。

以下是一个自定义 Package 的例子:

1
2
3
4
5
6
// greeting/greeting.go
package greeting

func Greet(name string) string {
return "Hello, " + name + "!"
}

在上面的例子中,我们创建了一个名为 greeting 的 Package,其中包含一个 Greet 函数,用于返回问候语。

1
2
3
4
5
6
7
8
9
// main.go
package main

import "fmt"
import "greeting"

func main() {
fmt.Println(greeting.Greet("world"))
}

在主函数中,我们导入 greeting Package,并使用 Greet 函数打印问候语。

通过 GMP 模型,Golang 提供了强大的并发编程能力,使得开发者能够轻松地处理大规模数据并发任务。当然,为了正确使用 GMP,开发者需要深入了解它们的实现细节。