Golang并发
协程的使用:
func()
执行一个函数go func()
开启一个协程执行函数
1. 信道chan
var pipline chan int
pipline:=make(chan int)
//发送数据
pipline<-1
//接收数据
data:=<-pipline
//关闭信道
close(pipline)
//ok表示chan是否被关闭,ok==true代表关闭
x,ok:=<-pipline
参数:
- chan类型
- chan容量(默认为0)
无缓冲信道:信道中不能存放数据,发送时必须被马上接收,若没有会被阻塞(同步)
有缓冲信道:可以缓存x个数据,用于多协程共享资源(异步)
双向信道:默认情况为双向信道,既可以接收也可以发送
单向信道:分为只读信道和只写信道
- 只读信道
var pipline = make(chan int)
type Receiver = <-chan int // 关键代码:定义别名类型
var receiver Receiver = pipline
- 只写信道
var pipline = make(chan int)
type Sender = chan<- int // 关键代码:定义别名类型
var sender Sender = pipline
遍历信道:
pipline := make(chan int, 10)
for x :=range pipline{
}
信道传递的值是否为深拷贝,取决于类型是引用类型还是值类型
从已关闭的 channel 读取消息不会产生 panic,且能读出 channel 中还未被读取的消息,若消息均已被读取,则会读取到该类型的零值。
从已关闭的 channel 读取消息永远不会阻塞,并且会返回一个为 false 的值
2. WaitGroup
实现一主多子的协程协作方式,使用 sync.WaitGroup
。
var group sync.WaitGroup
方法:
- Add 初始值为0,计数器加一,直接传入子协程的数量
- Done 某个子协程完成后调用该方法,计数器减一,通常通过defer调用
- Wait 阻塞当前协程,直到计数器归零
3. Golang锁
3.1 互斥锁 Mutex
目的:保护一个资源不会因为并发而引起冲突
//定义
var lock *sync.Mutex
lock=new(sync.Mutex)
lock:=&sync.Mutext{}
//加锁
lock.Lock()
//解锁
lock.Unlock()
3.2 读写锁 RWMutex
将程序对资源的访问分为读操作和写操作
- 为了保证数据的安全,其它协程写数据会阻塞
- 多协程读数据互不影响,不阻塞,不同于
Mutex
,只允许一个协程读数据
//定义
var lock *sync.RWMutex
lock=new(sync.RWMutex)
lock:=&sync.RWMutext{}
//加锁
lock.RLock()//读锁
lock.Lock()//写锁
//解锁
lock.RUnLock()
lock.Unlock()
4. Golang Context
当需要手动控制协程(关闭)的情况下,需要使用context
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
方法:
Deadline
,返回[截止时间,布尔值(true表示设置了截止时间)]
到了截止时间,自动触发Cancel,若没有截止时间,需要手动调用Cancel取消ContextDone
,返回一个只读的chan,类型为struct{}
,被cancel后会返回,若可读,意味着发起了cancelErr
,返回cancel的原因Value
,返回被绑定到Context的值,是一个键值对
根Context
var (
background = new(emptyCtx)
todo = new(emptyCtx)
)
func Background() Context {
return background
}
func TODO() Context {
return todo
}
Background
: 用于main函数,初始化以及测试代码中,作为Context树结构的顶层Context,不能被取消
TODO
:不知道该用什么Context时可以使用
本质上都是emptyCtx结构体类型,不可取消,无截止时间,不携带值的Context
Context
继承衍生
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
func WithValue(parent Context, key, val interface{}) Context