YMLiang

本章来讲什么是并发,了解并发的意义才能会用它

首先了解进程和线程
进程是资源分配的最小单位,线程是程序执行的最小单位。
进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。
线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
一个进程可以创建和撤销多个线程;同一个进程中的多个线程之间可以并发执行。

并发和并行

并发的关键是你有处理多个任务的能力,不一定要同时。
并行的关键是你有同时处理多个任务的能力。
所以我认为它们最关键的点就是:是否是同时。

goroutine的定义

任何函数只需加上go就能发送给调度器运行
不需要在定义时区分是否异步函数
调度器在合适的点进行切换

chan

channel 是 CSP 模式的具体实现,用于多个 goroutine 通讯。
其内部实现了同步,确保并发安全。多个goroutine同时访问,不需要加锁。

由于管道容量是5,开启go写入10个数据,再写入5个数据,会阻塞,然而read每秒会读取一个,然后在会写入一个数据。make(chan int,5)即给它一个5个大小的缓冲区

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

import (
"fmt"
"time"
)

func write(ch chan int) {
for i := 0; i < 10; i++ {
ch <- i
fmt.Println("put data:", i)
}
}

func read(ch chan int) {
for {
var b int
b = <-ch
fmt.Println(b)
time.Sleep(time.Second)
}
}

func main() {
intChan := make(chan int, 5)
go write(intChan)
go read(intChan)

time.Sleep(10 * time.Second)
}

WaitGroup

Golang 在语言层面对并发编程提供支持,一种类似协程,称作 goroutine 的机制。

只需在函数调用语句前添加 go 关键字,就可创建并发执行单元。开发人员无需了解任何执行细节,调度器会自动将其安排到合适的系统线程上执行。goroutine 是一种非常轻量级的实现,可在单个进程里执行成千上万的并发任务。

WaitGroup有三个方法

Add:添加或者减少等待goroutine的数量

Done:相当于Add(-1)

Wait:执行阻塞,直到所有的WaitGroup数量变成0

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
package main

import (
"fmt"
"sync"
"time"
)

func work(wg *sync.WaitGroup, i int) {
fmt.Println("work:", i)
time.Sleep(time.Second)
wg.Done()
}
func main() {
wg := sync.WaitGroup{}

for i := 0; i < 10; i++ {
wg.Add(1)
go work(&wg,i)
}

wg.Wait()
fmt.Println("goroutine finished")

}

go defer()

go defer (go延迟函数)
defer语句调用一个函数,这个函数执行会推迟,直到外围的函数返回,或者外围函数运行到最后,或者相应的goroutine panic

context

上下文管理
使用context保存上下文,比如你可以保存session,user_id,password到你的上下文中

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)

ctx.Done() //代表超时

适用于:任何请求的超时都可以用 ctx来控制

ctx也可以控制一个goroutine的生命周期

1
2


 评论


博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议

本站使用 Material X 作为主题 , 总访问量为 次 。
Copyright 2018-2019 YMLiang'BLOG   |   京ICP备 - 19039949  |  载入天数...载入时分秒...